2
2
3
3
use core:: cell:: RefCell ;
4
4
use core:: mem;
5
+ use core:: ops:: DerefMut ;
6
+ use ghost_cell:: GhostToken ;
5
7
use uefi:: boot:: { image_handle, OpenProtocolAttributes , OpenProtocolParams , ScopedProtocol } ;
6
8
use uefi:: proto:: pci:: root_bridge:: PciRootBridgeIo ;
7
9
use uefi:: proto:: pci:: PciIoAddress ;
@@ -27,45 +29,46 @@ pub fn test_io() {
27
29
let mut sata_ctrl_cnt = 0 ;
28
30
29
31
for pci_handle in pci_handles {
30
- let mut pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle ) ;
31
-
32
- for bus in 0 ..=255 {
33
- for dev in 0 ..32 {
34
- for fun in 0 ..8 {
35
- let addr = PciIoAddress :: new ( bus, dev, fun) ;
36
- let Ok ( reg0) = pci_proto. pci ( ) . read_one :: < u32 > ( addr. with_register ( 0 ) ) else {
37
- continue ;
38
- } ;
39
- if reg0 == 0xFFFFFFFF {
40
- continue ; // not a valid device
41
- }
42
- let reg1 = pci_proto
43
- . pci ( )
44
- . read_one :: < u32 > ( addr. with_register ( 2 * REG_SIZE ) )
45
- . unwrap ( ) ;
46
-
47
- let vendor_id = ( reg0 & 0xFFFF ) as u16 ;
48
- let device_id = ( reg0 >> 16 ) as u16 ;
49
- if vendor_id == RED_HAT_PCI_VENDOR_ID {
50
- red_hat_dev_cnt += 1 ;
51
- }
32
+ GhostToken :: new ( | mut token| {
33
+ let pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle ) ;
34
+ for bus in 0 ..=255 {
35
+ for dev in 0 ..32 {
36
+ for fun in 0 ..8 {
37
+ let addr = PciIoAddress :: new ( bus, dev, fun) ;
38
+ let Ok ( reg0) = pci_proto. pci ( & mut token ) . read_one :: < u32 > ( addr. with_register ( 0 ) ) else {
39
+ continue ;
40
+ } ;
41
+ if reg0 == 0xFFFFFFFF {
42
+ continue ; // not a valid device
43
+ }
44
+ let reg1 = pci_proto
45
+ . pci ( & mut token )
46
+ . read_one :: < u32 > ( addr. with_register ( 2 * REG_SIZE ) )
47
+ . unwrap ( ) ;
48
+
49
+ let vendor_id = ( reg0 & 0xFFFF ) as u16 ;
50
+ let device_id = ( reg0 >> 16 ) as u16 ;
51
+ if vendor_id == RED_HAT_PCI_VENDOR_ID {
52
+ red_hat_dev_cnt += 1 ;
53
+ }
52
54
53
- let class_code = ( reg1 >> 24 ) as u8 ;
54
- let subclass_code = ( ( reg1 >> 16 ) & 0xFF ) as u8 ;
55
- if class_code == MASS_STORAGE_CTRL_CLASS_CODE {
56
- mass_storage_ctrl_cnt += 1 ;
55
+ let class_code = ( reg1 >> 24 ) as u8 ;
56
+ let subclass_code = ( ( reg1 >> 16 ) & 0xFF ) as u8 ;
57
+ if class_code == MASS_STORAGE_CTRL_CLASS_CODE {
58
+ mass_storage_ctrl_cnt += 1 ;
57
59
58
- if subclass_code == SATA_CTRL_SUBCLASS_CODE {
59
- sata_ctrl_cnt += 1 ;
60
+ if subclass_code == SATA_CTRL_SUBCLASS_CODE {
61
+ sata_ctrl_cnt += 1 ;
62
+ }
60
63
}
61
- }
62
64
63
- log:: info!(
65
+ log:: info!(
64
66
"PCI Device: [{bus}, {dev}, {fun}]: vendor={vendor_id:04X}, device={device_id:04X}, class={class_code:02X}, subclass={subclass_code:02X}"
65
67
) ;
68
+ }
66
69
}
67
70
}
68
- }
71
+ } ) ;
69
72
}
70
73
71
74
assert ! ( red_hat_dev_cnt > 0 ) ;
@@ -77,106 +80,111 @@ pub fn test_buffer() {
77
80
let pci_handles = uefi:: boot:: find_handles :: < PciRootBridgeIo > ( ) . unwrap ( ) ;
78
81
79
82
for pci_handle in pci_handles {
80
- let pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle) ;
81
- let pci_proto: RefCell < _ > = pci_proto. into ( ) ;
82
-
83
- let mut buffer = PciRootBridgeIo :: allocate_buffer :: < [ u8 ; 4096 ] > (
84
- & pci_proto,
85
- MemoryType :: BOOT_SERVICES_DATA ,
86
- None ,
87
- PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
88
- )
89
- . unwrap ( ) ;
90
- let buffer = unsafe {
91
- buffer. assume_init_mut ( ) . fill ( 0 ) ;
92
- buffer. assume_init ( )
93
- } ;
94
- assert_eq ! ( buffer. as_ptr( ) . addr( ) % 4096 , 0 ) ;
83
+ GhostToken :: new ( |token| {
84
+ let pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle) ;
85
+ let token: RefCell < _ > = token. into ( ) ;
86
+ let mut buffer = pci_proto. allocate_buffer :: < [ u8 ; 4096 ] > (
87
+ & token,
88
+ MemoryType :: BOOT_SERVICES_DATA ,
89
+ None ,
90
+ PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
91
+ ) . unwrap ( ) ;
92
+
93
+ let buffer = unsafe {
94
+ buffer. assume_init_mut ( ) . fill ( 0 ) ;
95
+ buffer. assume_init ( )
96
+ } ;
97
+
98
+ assert_eq ! ( buffer. as_ptr( ) . addr( ) % 4096 , 0 ) ;
99
+ } ) ;
95
100
}
96
101
}
97
102
98
103
pub fn test_mapping ( ) {
99
104
let pci_handles = uefi:: boot:: find_handles :: < PciRootBridgeIo > ( ) . unwrap ( ) ;
100
105
101
106
for pci_handle in pci_handles {
102
- let pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle) ;
103
- let pci_proto: RefCell < _ > = pci_proto. into ( ) ;
104
-
105
- let mut buffer = PciRootBridgeIo :: allocate_buffer :: < [ u8 ; 4096 ] > (
106
- & pci_proto,
107
- MemoryType :: BOOT_SERVICES_DATA ,
108
- None ,
109
- PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
110
- )
111
- . unwrap ( ) ;
112
- let buffer = unsafe {
113
- buffer. assume_init_mut ( ) . fill ( 0 ) ;
114
- buffer. assume_init ( )
115
- } ;
116
-
117
- let mapped = PciRootBridgeIo :: map (
118
- & pci_proto,
119
- PciRootBridgeIoProtocolOperation :: BUS_MASTER_COMMON_BUFFER64 ,
120
- buffer. as_ref ( ) ,
121
- ) ;
122
- if mapped. region ( ) . device_address == buffer. as_ptr ( ) . addr ( ) as u64 {
123
- info ! ( "This PCI device uses identity mapping" ) ;
124
- } else {
125
- info ! ( "This PCI device uses different mapping from CPU" ) ;
126
- }
107
+ GhostToken :: new ( |token| {
108
+ let pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle) ;
109
+ let token: RefCell < _ > = token. into ( ) ;
110
+
111
+ let mut buffer = pci_proto. allocate_buffer :: < [ u8 ; 4096 ] > (
112
+ & token,
113
+ MemoryType :: BOOT_SERVICES_DATA ,
114
+ None ,
115
+ PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
116
+ ) . unwrap ( ) ;
117
+ let buffer = unsafe {
118
+ buffer. assume_init_mut ( ) . fill ( 0 ) ;
119
+ buffer. assume_init ( )
120
+ } ;
121
+
122
+ let mapped = pci_proto. map (
123
+ & token,
124
+ PciRootBridgeIoProtocolOperation :: BUS_MASTER_COMMON_BUFFER64 ,
125
+ buffer. as_ref ( ) ,
126
+ ) ;
127
+ if mapped. region ( ) . device_address == buffer. as_ptr ( ) . addr ( ) as u64 {
128
+ info ! ( "This PCI device uses identity mapping" ) ;
129
+ } else {
130
+ info ! ( "This PCI device uses different mapping from CPU" ) ;
131
+ }
132
+ } ) ;
127
133
}
128
134
}
129
135
130
136
pub fn test_copy ( ) {
131
137
let pci_handles = uefi:: boot:: find_handles :: < PciRootBridgeIo > ( ) . unwrap ( ) ;
132
138
133
139
for pci_handle in pci_handles {
134
- let pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle) ;
135
- let pci_proto: RefCell < _ > = pci_proto. into ( ) ;
136
-
137
- let mut src = PciRootBridgeIo :: allocate_buffer :: < [ u32 ; 4096 / 4 ] > (
138
- & pci_proto,
139
- MemoryType :: BOOT_SERVICES_DATA ,
140
- None ,
141
- PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
142
- )
143
- . unwrap ( ) ;
144
- assert_eq ! ( size_of_val( src. as_ref( ) ) , size_of:: <[ u8 ; PAGE_SIZE ] >( ) ) ;
145
- let src = unsafe {
146
- src. assume_init_mut ( ) . fill ( 0xDEADBEEF ) ;
147
- src. assume_init ( )
148
- } ;
149
- let src_mapped = PciRootBridgeIo :: map (
150
- & pci_proto,
151
- PciRootBridgeIoProtocolOperation :: BUS_MASTER_READ ,
152
- src. as_ref ( ) ,
153
- ) ;
154
-
155
- let dst = PciRootBridgeIo :: allocate_buffer :: < [ u32 ; 4096 / 4 ] > (
156
- & pci_proto,
157
- MemoryType :: BOOT_SERVICES_DATA ,
158
- None ,
159
- PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
160
- )
161
- . unwrap ( ) ;
162
- assert_eq ! ( size_of_val( dst. as_ref( ) ) , size_of:: <[ u8 ; PAGE_SIZE ] >( ) ) ;
163
- let dst_mapped = PciRootBridgeIo :: map (
164
- & pci_proto,
165
- PciRootBridgeIoProtocolOperation :: BUS_MASTER_WRITE ,
166
- dst. as_ref ( ) ,
167
- ) ;
168
-
169
- PciRootBridgeIo :: copy (
170
- & pci_proto,
171
- PciRootBridgeIoProtocolWidth :: UINT32 ,
172
- dst_mapped. region ( ) ,
173
- src_mapped. region ( ) ,
174
- )
175
- . unwrap ( ) ;
176
- drop ( dst_mapped) ;
177
- let dst = unsafe { dst. assume_init ( ) } ;
178
-
179
- assert ! ( dst. iter( ) . all( |& b| b == 0xDEADBEEF ) ) ;
140
+ GhostToken :: new ( |token| {
141
+ let pci_proto = get_open_protocol :: < PciRootBridgeIo > ( pci_handle) ;
142
+ let token: RefCell < _ > = token. into ( ) ;
143
+
144
+ let mut src = pci_proto. allocate_buffer :: < [ u32 ; 4096 / 4 ] > (
145
+ & token,
146
+ MemoryType :: BOOT_SERVICES_DATA ,
147
+ None ,
148
+ PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
149
+ ) . unwrap ( ) ;
150
+ assert_eq ! ( size_of_val( src. as_ref( ) ) , size_of:: <[ u8 ; PAGE_SIZE ] >( ) ) ;
151
+ let src = unsafe {
152
+ src. assume_init_mut ( ) . fill ( 0xDEADBEEF ) ;
153
+ src. assume_init ( )
154
+ } ;
155
+ let src_mapped = pci_proto. map (
156
+ & token,
157
+ PciRootBridgeIoProtocolOperation :: BUS_MASTER_READ ,
158
+ src. as_ref ( ) ,
159
+ ) ;
160
+
161
+ let dst = pci_proto. allocate_buffer :: < [ u32 ; 4096 / 4 ] > (
162
+ & token,
163
+ MemoryType :: BOOT_SERVICES_DATA ,
164
+ None ,
165
+ PciRootBridgeIoProtocolAttribute :: PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE ,
166
+ ) . unwrap ( ) ;
167
+ assert_eq ! ( size_of_val( dst. as_ref( ) ) , size_of:: <[ u8 ; PAGE_SIZE ] >( ) ) ;
168
+ let dst_mapped = pci_proto. map (
169
+ & token,
170
+ PciRootBridgeIoProtocolOperation :: BUS_MASTER_WRITE ,
171
+ dst. as_ref ( ) ,
172
+ ) ;
173
+
174
+ let width = PciRootBridgeIoProtocolWidth :: UINT32 ;
175
+ assert_eq ! ( width. size( ) , 4 ) ;
176
+
177
+ pci_proto. copy (
178
+ token. borrow_mut ( ) . deref_mut ( ) ,
179
+ width,
180
+ dst_mapped. region ( ) ,
181
+ src_mapped. region ( ) ,
182
+ ) . unwrap ( ) ;
183
+ drop ( dst_mapped) ;
184
+ let dst = unsafe { dst. assume_init ( ) } ;
185
+
186
+ assert ! ( dst. iter( ) . all( |& b| b == 0xDEADBEEF ) ) ;
187
+ } ) ;
180
188
}
181
189
}
182
190
0 commit comments