aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2012-12-05 16:33:26 -0500
committerBjorn Helgaas <bhelgaas@google.com>2012-12-05 16:33:26 -0500
commitdd5fc854de5fd37adfcef8a366cd21a55aa01d3d (patch)
tree48658057b6a005c93dfb54072585f432a96e934a
parent8f0d8163b50e01f398b14bcd4dc039ac5ab18d64 (diff)
EFI: Stash ROMs if they're not in the PCI BAR
EFI provides support for providing PCI ROMs via means other than the ROM BAR. This support vanishes after we've exited boot services, so add support for stashing copies of the ROMs in setup_data if they're not otherwise available. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Tested-by: Seth Forshee <seth.forshee@canonical.com>
-rw-r--r--arch/x86/boot/compressed/eboot.c118
-rw-r--r--arch/x86/include/asm/bootparam.h1
-rw-r--r--arch/x86/include/asm/pci.h12
-rw-r--r--include/linux/efi.h71
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
247static 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
357free_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 */
18struct setup_data { 19struct 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
174struct 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
199typedef 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
215typedef enum {
216 EfiPciIoAttributeOperationGet,
217 EfiPciIoAttributeOperationSet,
218 EfiPciIoAttributeOperationEnable,
219 EfiPciIoAttributeOperationDisable,
220 EfiPciIoAttributeOperationSupported,
221 EfiPciIoAttributeOperationMaximum
222} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION;
223
224
225typedef struct {
226 void *read;
227 void *write;
228} efi_pci_io_protocol_access_t;
229
230typedef 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 */