diff options
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 118 | ||||
-rw-r--r-- | arch/x86/include/asm/bootparam.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/pci.h | 12 | ||||
-rw-r--r-- | include/linux/efi.h | 71 |
4 files changed, 202 insertions, 0 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index c760e073963e..8a54313bc7dc 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * ----------------------------------------------------------------------- */ | 8 | * ----------------------------------------------------------------------- */ |
9 | 9 | ||
10 | #include <linux/efi.h> | 10 | #include <linux/efi.h> |
11 | #include <linux/pci.h> | ||
11 | #include <asm/efi.h> | 12 | #include <asm/efi.h> |
12 | #include <asm/setup.h> | 13 | #include <asm/setup.h> |
13 | #include <asm/desc.h> | 14 | #include <asm/desc.h> |
@@ -243,6 +244,121 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size) | |||
243 | *size = len; | 244 | *size = len; |
244 | } | 245 | } |
245 | 246 | ||
247 | static efi_status_t setup_efi_pci(struct boot_params *params) | ||
248 | { | ||
249 | efi_pci_io_protocol *pci; | ||
250 | efi_status_t status; | ||
251 | void **pci_handle; | ||
252 | efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; | ||
253 | unsigned long nr_pci, size = 0; | ||
254 | int i; | ||
255 | struct setup_data *data; | ||
256 | |||
257 | data = (struct setup_data *)params->hdr.setup_data; | ||
258 | |||
259 | while (data && data->next) | ||
260 | data = (struct setup_data *)data->next; | ||
261 | |||
262 | status = efi_call_phys5(sys_table->boottime->locate_handle, | ||
263 | EFI_LOCATE_BY_PROTOCOL, &pci_proto, | ||
264 | NULL, &size, pci_handle); | ||
265 | |||
266 | if (status == EFI_BUFFER_TOO_SMALL) { | ||
267 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
268 | EFI_LOADER_DATA, size, &pci_handle); | ||
269 | |||
270 | if (status != EFI_SUCCESS) | ||
271 | return status; | ||
272 | |||
273 | status = efi_call_phys5(sys_table->boottime->locate_handle, | ||
274 | EFI_LOCATE_BY_PROTOCOL, &pci_proto, | ||
275 | NULL, &size, pci_handle); | ||
276 | } | ||
277 | |||
278 | if (status != EFI_SUCCESS) | ||
279 | goto free_handle; | ||
280 | |||
281 | nr_pci = size / sizeof(void *); | ||
282 | for (i = 0; i < nr_pci; i++) { | ||
283 | void *h = pci_handle[i]; | ||
284 | uint64_t attributes; | ||
285 | struct pci_setup_rom *rom; | ||
286 | |||
287 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | ||
288 | h, &pci_proto, &pci); | ||
289 | |||
290 | if (status != EFI_SUCCESS) | ||
291 | continue; | ||
292 | |||
293 | if (!pci) | ||
294 | continue; | ||
295 | |||
296 | status = efi_call_phys4(pci->attributes, pci, | ||
297 | EfiPciIoAttributeOperationGet, 0, | ||
298 | &attributes); | ||
299 | |||
300 | if (status != EFI_SUCCESS) | ||
301 | continue; | ||
302 | |||
303 | if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) | ||
304 | continue; | ||
305 | |||
306 | if (!pci->romimage || !pci->romsize) | ||
307 | continue; | ||
308 | |||
309 | size = pci->romsize + sizeof(*rom); | ||
310 | |||
311 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | ||
312 | EFI_LOADER_DATA, size, &rom); | ||
313 | |||
314 | if (status != EFI_SUCCESS) | ||
315 | continue; | ||
316 | |||
317 | rom->data.type = SETUP_PCI; | ||
318 | rom->data.len = size - sizeof(struct setup_data); | ||
319 | rom->data.next = 0; | ||
320 | rom->pcilen = pci->romsize; | ||
321 | |||
322 | status = efi_call_phys5(pci->pci.read, pci, | ||
323 | EfiPciIoWidthUint16, PCI_VENDOR_ID, | ||
324 | 1, &(rom->vendor)); | ||
325 | |||
326 | if (status != EFI_SUCCESS) | ||
327 | goto free_struct; | ||
328 | |||
329 | status = efi_call_phys5(pci->pci.read, pci, | ||
330 | EfiPciIoWidthUint16, PCI_DEVICE_ID, | ||
331 | 1, &(rom->devid)); | ||
332 | |||
333 | if (status != EFI_SUCCESS) | ||
334 | goto free_struct; | ||
335 | |||
336 | status = efi_call_phys5(pci->get_location, pci, | ||
337 | &(rom->segment), &(rom->bus), | ||
338 | &(rom->device), &(rom->function)); | ||
339 | |||
340 | if (status != EFI_SUCCESS) | ||
341 | goto free_struct; | ||
342 | |||
343 | memcpy(rom->romdata, pci->romimage, pci->romsize); | ||
344 | |||
345 | if (data) | ||
346 | data->next = (uint64_t)rom; | ||
347 | else | ||
348 | params->hdr.setup_data = (uint64_t)rom; | ||
349 | |||
350 | data = (struct setup_data *)rom; | ||
351 | |||
352 | continue; | ||
353 | free_struct: | ||
354 | efi_call_phys1(sys_table->boottime->free_pool, rom); | ||
355 | } | ||
356 | |||
357 | free_handle: | ||
358 | efi_call_phys1(sys_table->boottime->free_pool, pci_handle); | ||
359 | return status; | ||
360 | } | ||
361 | |||
246 | /* | 362 | /* |
247 | * See if we have Graphics Output Protocol | 363 | * See if we have Graphics Output Protocol |
248 | */ | 364 | */ |
@@ -1026,6 +1142,8 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table, | |||
1026 | 1142 | ||
1027 | setup_graphics(boot_params); | 1143 | setup_graphics(boot_params); |
1028 | 1144 | ||
1145 | setup_efi_pci(boot_params); | ||
1146 | |||
1029 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | 1147 | status = efi_call_phys3(sys_table->boottime->allocate_pool, |
1030 | EFI_LOADER_DATA, sizeof(*gdt), | 1148 | EFI_LOADER_DATA, sizeof(*gdt), |
1031 | (void **)&gdt); | 1149 | (void **)&gdt); |
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 2ad874cb661c..92862cd90201 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #define SETUP_NONE 0 | 13 | #define SETUP_NONE 0 |
14 | #define SETUP_E820_EXT 1 | 14 | #define SETUP_E820_EXT 1 |
15 | #define SETUP_DTB 2 | 15 | #define SETUP_DTB 2 |
16 | #define SETUP_PCI 3 | ||
16 | 17 | ||
17 | /* extensible setup data list node */ | 18 | /* extensible setup data list node */ |
18 | struct setup_data { | 19 | struct setup_data { |
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 6e41b9343928..dba7805176bf 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -171,4 +171,16 @@ cpumask_of_pcibus(const struct pci_bus *bus) | |||
171 | } | 171 | } |
172 | #endif | 172 | #endif |
173 | 173 | ||
174 | struct pci_setup_rom { | ||
175 | struct setup_data data; | ||
176 | uint16_t vendor; | ||
177 | uint16_t devid; | ||
178 | uint64_t pcilen; | ||
179 | unsigned long segment; | ||
180 | unsigned long bus; | ||
181 | unsigned long device; | ||
182 | unsigned long function; | ||
183 | uint8_t romdata[0]; | ||
184 | }; | ||
185 | |||
174 | #endif /* _ASM_X86_PCI_H */ | 186 | #endif /* _ASM_X86_PCI_H */ |
diff --git a/include/linux/efi.h b/include/linux/efi.h index 8670eb1eb8cd..8eb1be17c801 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -196,6 +196,77 @@ typedef struct { | |||
196 | void *create_event_ex; | 196 | void *create_event_ex; |
197 | } efi_boot_services_t; | 197 | } efi_boot_services_t; |
198 | 198 | ||
199 | typedef enum { | ||
200 | EfiPciIoWidthUint8, | ||
201 | EfiPciIoWidthUint16, | ||
202 | EfiPciIoWidthUint32, | ||
203 | EfiPciIoWidthUint64, | ||
204 | EfiPciIoWidthFifoUint8, | ||
205 | EfiPciIoWidthFifoUint16, | ||
206 | EfiPciIoWidthFifoUint32, | ||
207 | EfiPciIoWidthFifoUint64, | ||
208 | EfiPciIoWidthFillUint8, | ||
209 | EfiPciIoWidthFillUint16, | ||
210 | EfiPciIoWidthFillUint32, | ||
211 | EfiPciIoWidthFillUint64, | ||
212 | EfiPciIoWidthMaximum | ||
213 | } EFI_PCI_IO_PROTOCOL_WIDTH; | ||
214 | |||
215 | typedef enum { | ||
216 | EfiPciIoAttributeOperationGet, | ||
217 | EfiPciIoAttributeOperationSet, | ||
218 | EfiPciIoAttributeOperationEnable, | ||
219 | EfiPciIoAttributeOperationDisable, | ||
220 | EfiPciIoAttributeOperationSupported, | ||
221 | EfiPciIoAttributeOperationMaximum | ||
222 | } EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; | ||
223 | |||
224 | |||
225 | typedef struct { | ||
226 | void *read; | ||
227 | void *write; | ||
228 | } efi_pci_io_protocol_access_t; | ||
229 | |||
230 | typedef struct { | ||
231 | void *poll_mem; | ||
232 | void *poll_io; | ||
233 | efi_pci_io_protocol_access_t mem; | ||
234 | efi_pci_io_protocol_access_t io; | ||
235 | efi_pci_io_protocol_access_t pci; | ||
236 | void *copy_mem; | ||
237 | void *map; | ||
238 | void *unmap; | ||
239 | void *allocate_buffer; | ||
240 | void *free_buffer; | ||
241 | void *flush; | ||
242 | void *get_location; | ||
243 | void *attributes; | ||
244 | void *get_bar_attributes; | ||
245 | void *set_bar_attributes; | ||
246 | uint64_t romsize; | ||
247 | void *romimage; | ||
248 | } efi_pci_io_protocol; | ||
249 | |||
250 | #define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 | ||
251 | #define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 | ||
252 | #define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 | ||
253 | #define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 | ||
254 | #define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 | ||
255 | #define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 | ||
256 | #define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 | ||
257 | #define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 | ||
258 | #define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 | ||
259 | #define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 | ||
260 | #define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 | ||
261 | #define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 | ||
262 | #define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 | ||
263 | #define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 | ||
264 | #define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 | ||
265 | #define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 | ||
266 | #define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 | ||
267 | #define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 | ||
268 | #define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x40000 | ||
269 | |||
199 | /* | 270 | /* |
200 | * Types and defines for EFI ResetSystem | 271 | * Types and defines for EFI ResetSystem |
201 | */ | 272 | */ |