aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2014-01-16 06:35:43 -0500
committerMatt Fleming <matt.fleming@intel.com>2014-03-04 16:25:05 -0500
commitc116e8d60adabfd545a269fccab85e77febc1643 (patch)
treedc78d4b4782819331528d45235688dc9cb3ed4b7 /arch/x86
parent0154416a71c2a84c3746c8dd8ed25287e36934d3 (diff)
x86/efi: Split the boot stub into 32/64 code paths
Make the decision which code path to take at runtime based on efi_early->is64. Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/boot/compressed/eboot.c814
1 files changed, 637 insertions, 177 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 42548168bdc3..ab1f3a2f1e1e 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -49,10 +49,63 @@ static void efi_printk(efi_system_table_t *, char *);
49static void efi_char16_printk(efi_system_table_t *, efi_char16_t *); 49static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
50 50
51static efi_status_t 51static efi_status_t
52efi_file_size(efi_system_table_t *sys_table, void *__fh, 52__file_size32(void *__fh, efi_char16_t *filename_16,
53 efi_char16_t *filename_16, void **handle, u64 *file_sz) 53 void **handle, u64 *file_sz)
54{
55 efi_file_handle_32_t *h, *fh = __fh;
56 efi_file_info_t *info;
57 efi_status_t status;
58 efi_guid_t info_guid = EFI_FILE_INFO_ID;
59 u32 info_sz;
60
61 status = efi_early->call((unsigned long)fh->open, fh, &h, filename_16,
62 EFI_FILE_MODE_READ, (u64)0);
63 if (status != EFI_SUCCESS) {
64 efi_printk(sys_table, "Failed to open file: ");
65 efi_char16_printk(sys_table, filename_16);
66 efi_printk(sys_table, "\n");
67 return status;
68 }
69
70 *handle = h;
71
72 info_sz = 0;
73 status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
74 &info_sz, NULL);
75 if (status != EFI_BUFFER_TOO_SMALL) {
76 efi_printk(sys_table, "Failed to get file info size\n");
77 return status;
78 }
79
80grow:
81 status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
82 info_sz, (void **)&info);
83 if (status != EFI_SUCCESS) {
84 efi_printk(sys_table, "Failed to alloc mem for file info\n");
85 return status;
86 }
87
88 status = efi_early->call((unsigned long)h->get_info, h, &info_guid,
89 &info_sz, info);
90 if (status == EFI_BUFFER_TOO_SMALL) {
91 efi_early->call(efi_early->free_pool, info);
92 goto grow;
93 }
94
95 *file_sz = info->file_size;
96 efi_early->call(efi_early->free_pool, info);
97
98 if (status != EFI_SUCCESS)
99 efi_printk(sys_table, "Failed to get initrd info\n");
100
101 return status;
102}
103
104static efi_status_t
105__file_size64(void *__fh, efi_char16_t *filename_16,
106 void **handle, u64 *file_sz)
54{ 107{
55 efi_file_handle_t *h, *fh = __fh; 108 efi_file_handle_64_t *h, *fh = __fh;
56 efi_file_info_t *info; 109 efi_file_info_t *info;
57 efi_status_t status; 110 efi_status_t status;
58 efi_guid_t info_guid = EFI_FILE_INFO_ID; 111 efi_guid_t info_guid = EFI_FILE_INFO_ID;
@@ -100,31 +153,82 @@ grow:
100 153
101 return status; 154 return status;
102} 155}
156static efi_status_t
157efi_file_size(efi_system_table_t *sys_table, void *__fh,
158 efi_char16_t *filename_16, void **handle, u64 *file_sz)
159{
160 if (efi_early->is64)
161 return __file_size64(__fh, filename_16, handle, file_sz);
162
163 return __file_size32(__fh, filename_16, handle, file_sz);
164}
103 165
104static inline efi_status_t 166static inline efi_status_t
105efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr) 167efi_file_read(void *__fh, void *handle, unsigned long *size, void *addr)
106{ 168{
107 efi_file_handle_t *fh = __fh; 169 unsigned long func;
108 return efi_early->call((unsigned long)fh->read, handle, size, addr); 170
171 if (efi_early->is64) {
172 efi_file_handle_64_t *fh = __fh;
173
174 func = (unsigned long)fh->read;
175 return efi_early->call(func, handle, size, addr);
176 } else {
177 efi_file_handle_32_t *fh = __fh;
178
179 func = (unsigned long)fh->read;
180 return efi_early->call(func, handle, size, addr);
181 }
109} 182}
110 183
111static inline efi_status_t efi_file_close(void *__fh, void *handle) 184static inline efi_status_t efi_file_close(void *__fh, void *handle)
112{ 185{
113 efi_file_handle_t *fh = __fh; 186 if (efi_early->is64) {
187 efi_file_handle_64_t *fh = __fh;
114 188
115 return efi_early->call((unsigned long)fh->close, handle); 189 return efi_early->call((unsigned long)fh->close, handle);
190 } else {
191 efi_file_handle_32_t *fh = __fh;
192
193 return efi_early->call((unsigned long)fh->close, handle);
194 }
116} 195}
117 196
118static inline efi_status_t 197static inline efi_status_t __open_volume32(void *__image, void **__fh)
119efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh) 198{
199 efi_file_io_interface_t *io;
200 efi_loaded_image_32_t *image = __image;
201 efi_file_handle_32_t *fh;
202 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
203 efi_status_t status;
204 void *handle = (void *)(unsigned long)image->device_handle;
205 unsigned long func;
206
207 status = efi_early->call(efi_early->handle_protocol, handle,
208 &fs_proto, (void **)&io);
209 if (status != EFI_SUCCESS) {
210 efi_printk(sys_table, "Failed to handle fs_proto\n");
211 return status;
212 }
213
214 func = (unsigned long)io->open_volume;
215 status = efi_early->call(func, io, &fh);
216 if (status != EFI_SUCCESS)
217 efi_printk(sys_table, "Failed to open volume\n");
218
219 *__fh = fh;
220 return status;
221}
222
223static inline efi_status_t __open_volume64(void *__image, void **__fh)
120{ 224{
121 efi_file_io_interface_t *io; 225 efi_file_io_interface_t *io;
122 efi_loaded_image_t *image = __image; 226 efi_loaded_image_64_t *image = __image;
123 efi_file_handle_t *fh; 227 efi_file_handle_64_t *fh;
124 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID; 228 efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
125 efi_status_t status; 229 efi_status_t status;
126 void *handle = (void *)(unsigned long)image->device_handle; 230 void *handle = (void *)(unsigned long)image->device_handle;
127 u32 func; 231 unsigned long func;
128 232
129 status = efi_early->call(efi_early->handle_protocol, handle, 233 status = efi_early->call(efi_early->handle_protocol, handle,
130 &fs_proto, (void **)&io); 234 &fs_proto, (void **)&io);
@@ -142,19 +246,39 @@ efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
142 return status; 246 return status;
143} 247}
144 248
145static inline void 249static inline efi_status_t
146efi_char16_printk(efi_system_table_t *table, efi_char16_t *str) 250efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
251{
252 if (efi_early->is64)
253 return __open_volume64(__image, __fh);
254
255 return __open_volume32(__image, __fh);
256}
257
258static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
147{ 259{
148 struct efi_simple_text_output_protocol *out;
149 unsigned long output_string; 260 unsigned long output_string;
150 size_t offset; 261 size_t offset;
151 unsigned long *func;
152 262
153 offset = offsetof(typeof(*out), output_string); 263 if (efi_early->is64) {
154 output_string = efi_early->text_output + offset; 264 struct efi_simple_text_output_protocol_64 *out;
155 func = (unsigned long *)output_string; 265 u64 *func;
266
267 offset = offsetof(typeof(*out), output_string);
268 output_string = efi_early->text_output + offset;
269 func = (u64 *)output_string;
270
271 efi_early->call(*func, efi_early->text_output, str);
272 } else {
273 struct efi_simple_text_output_protocol_32 *out;
274 u32 *func;
275
276 offset = offsetof(typeof(*out), output_string);
277 output_string = efi_early->text_output + offset;
278 func = (u32 *)output_string;
156 279
157 efi_early->call(*func, efi_early->text_output, str); 280 efi_early->call(*func, efi_early->text_output, str);
281 }
158} 282}
159 283
160#include "../../../../drivers/firmware/efi/efi-stub-helper.c" 284#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
@@ -182,46 +306,86 @@ static void find_bits(unsigned long mask, u8 *pos, u8 *size)
182 *size = len; 306 *size = len;
183} 307}
184 308
185static efi_status_t setup_efi_pci(struct boot_params *params) 309static efi_status_t
310__setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
186{ 311{
187 efi_pci_io_protocol *pci; 312 struct pci_setup_rom *rom = NULL;
188 efi_status_t status; 313 efi_status_t status;
189 void **pci_handle = NULL; 314 unsigned long size;
190 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID; 315 uint64_t attributes;
191 unsigned long nr_pci, size = 0;
192 int i;
193 struct setup_data *data;
194 316
195 data = (struct setup_data *)(unsigned long)params->hdr.setup_data; 317 status = efi_early->call(pci->attributes, pci,
318 EfiPciIoAttributeOperationGet, 0, 0,
319 &attributes);
320 if (status != EFI_SUCCESS)
321 return status;
196 322
197 while (data && data->next) 323 if (!pci->romimage || !pci->romsize)
198 data = (struct setup_data *)(unsigned long)data->next; 324 return EFI_INVALID_PARAMETER;
199 325
200 status = efi_early->call(efi_early->locate_handle, 326 size = pci->romsize + sizeof(*rom);
201 EFI_LOCATE_BY_PROTOCOL,
202 &pci_proto, NULL, &size, pci_handle);
203 327
204 if (status == EFI_BUFFER_TOO_SMALL) { 328 status = efi_early->call(efi_early->allocate_pool,
205 status = efi_early->call(efi_early->allocate_pool, 329 EFI_LOADER_DATA, size, &rom);
206 EFI_LOADER_DATA,
207 size, (void **)&pci_handle);
208 330
209 if (status != EFI_SUCCESS) 331 if (status != EFI_SUCCESS)
210 return status; 332 return status;
211 333
212 status = efi_early->call(efi_early->locate_handle, 334 memset(rom, 0, sizeof(*rom));
213 EFI_LOCATE_BY_PROTOCOL, &pci_proto, 335
214 NULL, &size, pci_handle); 336 rom->data.type = SETUP_PCI;
215 } 337 rom->data.len = size - sizeof(struct setup_data);
338 rom->data.next = 0;
339 rom->pcilen = pci->romsize;
340 *__rom = rom;
341
342 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
343 PCI_VENDOR_ID, 1, &(rom->vendor));
216 344
217 if (status != EFI_SUCCESS) 345 if (status != EFI_SUCCESS)
218 goto free_handle; 346 goto free_struct;
347
348 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
349 PCI_DEVICE_ID, 1, &(rom->devid));
350
351 if (status != EFI_SUCCESS)
352 goto free_struct;
219 353
220 nr_pci = size / sizeof(void *); 354 status = efi_early->call(pci->get_location, pci, &(rom->segment),
355 &(rom->bus), &(rom->device), &(rom->function));
356
357 if (status != EFI_SUCCESS)
358 goto free_struct;
359
360 memcpy(rom->romdata, pci->romimage, pci->romsize);
361 return status;
362
363free_struct:
364 efi_early->call(efi_early->free_pool, rom);
365 return status;
366}
367
368static efi_status_t
369setup_efi_pci32(struct boot_params *params, void **pci_handle,
370 unsigned long size)
371{
372 efi_pci_io_protocol_32 *pci = NULL;
373 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
374 u32 *handles = (u32 *)(unsigned long)pci_handle;
375 efi_status_t status;
376 unsigned long nr_pci;
377 struct setup_data *data;
378 int i;
379
380 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
381
382 while (data && data->next)
383 data = (struct setup_data *)(unsigned long)data->next;
384
385 nr_pci = size / sizeof(u32);
221 for (i = 0; i < nr_pci; i++) { 386 for (i = 0; i < nr_pci; i++) {
222 void *h = pci_handle[i]; 387 struct pci_setup_rom *rom = NULL;
223 uint64_t attributes; 388 u32 h = handles[i];
224 struct pci_setup_rom *rom;
225 389
226 status = efi_early->call(efi_early->handle_protocol, h, 390 status = efi_early->call(efi_early->handle_protocol, h,
227 &pci_proto, (void **)&pci); 391 &pci_proto, (void **)&pci);
@@ -232,56 +396,114 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
232 if (!pci) 396 if (!pci)
233 continue; 397 continue;
234 398
235#ifdef CONFIG_X86_64 399 status = __setup_efi_pci32(pci, &rom);
236 status = efi_early->call((unsigned long)pci->attributes, pci,
237 EfiPciIoAttributeOperationGet, 0,
238 &attributes);
239#else
240 status = efi_early->call((unsigned long)pci->attributes, pci,
241 EfiPciIoAttributeOperationGet, 0, 0,
242 &attributes);
243#endif
244 if (status != EFI_SUCCESS) 400 if (status != EFI_SUCCESS)
245 continue; 401 continue;
246 402
247 if (!pci->romimage || !pci->romsize) 403 if (data)
248 continue; 404 data->next = (unsigned long)rom;
405 else
406 params->hdr.setup_data = (unsigned long)rom;
249 407
250 size = pci->romsize + sizeof(*rom); 408 data = (struct setup_data *)rom;
251 409
252 status = efi_early->call(efi_early->allocate_pool, 410 }
253 EFI_LOADER_DATA, size, &rom);
254 411
255 if (status != EFI_SUCCESS) 412 return status;
256 continue; 413}
257 414
258 rom->data.type = SETUP_PCI; 415static efi_status_t
259 rom->data.len = size - sizeof(struct setup_data); 416__setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
260 rom->data.next = 0; 417{
261 rom->pcilen = pci->romsize; 418 struct pci_setup_rom *rom;
419 efi_status_t status;
420 unsigned long size;
421 uint64_t attributes;
262 422
263 status = efi_early->call((unsigned long)pci->pci.read, pci, 423 status = efi_early->call(pci->attributes, pci,
264 EfiPciIoWidthUint16, PCI_VENDOR_ID, 424 EfiPciIoAttributeOperationGet, 0,
265 1, &(rom->vendor)); 425 &attributes);
426 if (status != EFI_SUCCESS)
427 return status;
266 428
267 if (status != EFI_SUCCESS) 429 if (!pci->romimage || !pci->romsize)
268 goto free_struct; 430 return EFI_INVALID_PARAMETER;
269 431
270 status = efi_early->call((unsigned long)pci->pci.read, pci, 432 size = pci->romsize + sizeof(*rom);
271 EfiPciIoWidthUint16, PCI_DEVICE_ID,
272 1, &(rom->devid));
273 433
274 if (status != EFI_SUCCESS) 434 status = efi_early->call(efi_early->allocate_pool,
275 goto free_struct; 435 EFI_LOADER_DATA, size, &rom);
436
437 if (status != EFI_SUCCESS)
438 return status;
439
440 rom->data.type = SETUP_PCI;
441 rom->data.len = size - sizeof(struct setup_data);
442 rom->data.next = 0;
443 rom->pcilen = pci->romsize;
444 *__rom = rom;
445
446 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
447 PCI_VENDOR_ID, 1, &(rom->vendor));
448
449 if (status != EFI_SUCCESS)
450 goto free_struct;
451
452 status = efi_early->call(pci->pci.read, pci, EfiPciIoWidthUint16,
453 PCI_DEVICE_ID, 1, &(rom->devid));
454
455 if (status != EFI_SUCCESS)
456 goto free_struct;
457
458 status = efi_early->call(pci->get_location, pci, &(rom->segment),
459 &(rom->bus), &(rom->device), &(rom->function));
276 460
277 status = efi_early->call((unsigned long)pci->get_location, pci, 461 if (status != EFI_SUCCESS)
278 &(rom->segment), &(rom->bus), 462 goto free_struct;
279 &(rom->device), &(rom->function)); 463
464 memcpy(rom->romdata, pci->romimage, pci->romsize);
465 return status;
466
467free_struct:
468 efi_early->call(efi_early->free_pool, rom);
469 return status;
470
471}
472
473static efi_status_t
474setup_efi_pci64(struct boot_params *params, void **pci_handle,
475 unsigned long size)
476{
477 efi_pci_io_protocol_64 *pci = NULL;
478 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
479 u64 *handles = (u64 *)(unsigned long)pci_handle;
480 efi_status_t status;
481 unsigned long nr_pci;
482 struct setup_data *data;
483 int i;
484
485 data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
486
487 while (data && data->next)
488 data = (struct setup_data *)(unsigned long)data->next;
489
490 nr_pci = size / sizeof(u64);
491 for (i = 0; i < nr_pci; i++) {
492 struct pci_setup_rom *rom = NULL;
493 u64 h = handles[i];
494
495 status = efi_early->call(efi_early->handle_protocol, h,
496 &pci_proto, (void **)&pci);
280 497
281 if (status != EFI_SUCCESS) 498 if (status != EFI_SUCCESS)
282 goto free_struct; 499 continue;
500
501 if (!pci)
502 continue;
283 503
284 memcpy(rom->romdata, pci->romimage, pci->romsize); 504 status = __setup_efi_pci64(pci, &rom);
505 if (status != EFI_SUCCESS)
506 continue;
285 507
286 if (data) 508 if (data)
287 data->next = (unsigned long)rom; 509 data->next = (unsigned long)rom;
@@ -290,56 +512,250 @@ static efi_status_t setup_efi_pci(struct boot_params *params)
290 512
291 data = (struct setup_data *)rom; 513 data = (struct setup_data *)rom;
292 514
293 continue;
294 free_struct:
295 efi_early->call(efi_early->free_pool, rom);
296 } 515 }
297 516
517 return status;
518}
519
520static efi_status_t setup_efi_pci(struct boot_params *params)
521{
522 efi_status_t status;
523 void **pci_handle = NULL;
524 efi_guid_t pci_proto = EFI_PCI_IO_PROTOCOL_GUID;
525 unsigned long size = 0;
526
527 status = efi_early->call(efi_early->locate_handle,
528 EFI_LOCATE_BY_PROTOCOL,
529 &pci_proto, NULL, &size, pci_handle);
530
531 if (status == EFI_BUFFER_TOO_SMALL) {
532 status = efi_early->call(efi_early->allocate_pool,
533 EFI_LOADER_DATA,
534 size, (void **)&pci_handle);
535
536 if (status != EFI_SUCCESS)
537 return status;
538
539 status = efi_early->call(efi_early->locate_handle,
540 EFI_LOCATE_BY_PROTOCOL, &pci_proto,
541 NULL, &size, pci_handle);
542 }
543
544 if (status != EFI_SUCCESS)
545 goto free_handle;
546
547 if (efi_early->is64)
548 status = setup_efi_pci64(params, pci_handle, size);
549 else
550 status = setup_efi_pci32(params, pci_handle, size);
551
298free_handle: 552free_handle:
299 efi_early->call(efi_early->free_pool, pci_handle); 553 efi_early->call(efi_early->free_pool, pci_handle);
300 return status; 554 return status;
301} 555}
302 556
303/* 557static void
304 * See if we have Graphics Output Protocol 558setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
305 */ 559 struct efi_pixel_bitmask pixel_info, int pixel_format)
306static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
307 unsigned long size)
308{ 560{
309 struct efi_graphics_output_protocol *gop, *first_gop; 561 if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
310 struct efi_pixel_bitmask pixel_info; 562 si->lfb_depth = 32;
311 unsigned long nr_gops; 563 si->lfb_linelength = pixels_per_scan_line * 4;
564 si->red_size = 8;
565 si->red_pos = 0;
566 si->green_size = 8;
567 si->green_pos = 8;
568 si->blue_size = 8;
569 si->blue_pos = 16;
570 si->rsvd_size = 8;
571 si->rsvd_pos = 24;
572 } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
573 si->lfb_depth = 32;
574 si->lfb_linelength = pixels_per_scan_line * 4;
575 si->red_size = 8;
576 si->red_pos = 16;
577 si->green_size = 8;
578 si->green_pos = 8;
579 si->blue_size = 8;
580 si->blue_pos = 0;
581 si->rsvd_size = 8;
582 si->rsvd_pos = 24;
583 } else if (pixel_format == PIXEL_BIT_MASK) {
584 find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size);
585 find_bits(pixel_info.green_mask, &si->green_pos,
586 &si->green_size);
587 find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size);
588 find_bits(pixel_info.reserved_mask, &si->rsvd_pos,
589 &si->rsvd_size);
590 si->lfb_depth = si->red_size + si->green_size +
591 si->blue_size + si->rsvd_size;
592 si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
593 } else {
594 si->lfb_depth = 4;
595 si->lfb_linelength = si->lfb_width / 2;
596 si->red_size = 0;
597 si->red_pos = 0;
598 si->green_size = 0;
599 si->green_pos = 0;
600 si->blue_size = 0;
601 si->blue_pos = 0;
602 si->rsvd_size = 0;
603 si->rsvd_pos = 0;
604 }
605}
606
607static efi_status_t
608__gop_query32(struct efi_graphics_output_protocol_32 *gop32,
609 struct efi_graphics_output_mode_info **info,
610 unsigned long *size, u32 *fb_base)
611{
612 struct efi_graphics_output_protocol_mode_32 *mode;
312 efi_status_t status; 613 efi_status_t status;
313 void **gop_handle = NULL; 614 unsigned long m;
615
616 m = gop32->mode;
617 mode = (struct efi_graphics_output_protocol_mode_32 *)m;
618
619 status = efi_early->call(gop32->query_mode, gop32,
620 mode->mode, size, info);
621 if (status != EFI_SUCCESS)
622 return status;
623
624 *fb_base = mode->frame_buffer_base;
625 return status;
626}
627
628static efi_status_t
629setup_gop32(struct screen_info *si, efi_guid_t *proto,
630 unsigned long size, void **gop_handle)
631{
632 struct efi_graphics_output_protocol_32 *gop32, *first_gop;
633 unsigned long nr_gops;
314 u16 width, height; 634 u16 width, height;
315 u32 fb_base, fb_size;
316 u32 pixels_per_scan_line; 635 u32 pixels_per_scan_line;
636 u32 fb_base;
637 struct efi_pixel_bitmask pixel_info;
317 int pixel_format; 638 int pixel_format;
639 efi_status_t status;
640 u32 *handles = (u32 *)(unsigned long)gop_handle;
318 int i; 641 int i;
319 642
320 status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA, 643 first_gop = NULL;
321 size, (void **)&gop_handle); 644 gop32 = NULL;
645
646 nr_gops = size / sizeof(u32);
647 for (i = 0; i < nr_gops; i++) {
648 struct efi_graphics_output_mode_info *info = NULL;
649 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
650 bool conout_found = false;
651 void *dummy = NULL;
652 u32 h = handles[i];
653
654 status = efi_early->call(efi_early->handle_protocol, h,
655 proto, (void **)&gop32);
656 if (status != EFI_SUCCESS)
657 continue;
658
659 status = efi_early->call(efi_early->handle_protocol, h,
660 &conout_proto, &dummy);
661 if (status == EFI_SUCCESS)
662 conout_found = true;
663
664 status = __gop_query32(gop32, &info, &size, &fb_base);
665 if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
666 /*
667 * Systems that use the UEFI Console Splitter may
668 * provide multiple GOP devices, not all of which are
669 * backed by real hardware. The workaround is to search
670 * for a GOP implementing the ConOut protocol, and if
671 * one isn't found, to just fall back to the first GOP.
672 */
673 width = info->horizontal_resolution;
674 height = info->vertical_resolution;
675 pixel_format = info->pixel_format;
676 pixel_info = info->pixel_information;
677 pixels_per_scan_line = info->pixels_per_scan_line;
678
679 /*
680 * Once we've found a GOP supporting ConOut,
681 * don't bother looking any further.
682 */
683 first_gop = gop32;
684 if (conout_found)
685 break;
686 }
687 }
688
689 /* Did we find any GOPs? */
690 if (!first_gop)
691 goto out;
692
693 /* EFI framebuffer */
694 si->orig_video_isVGA = VIDEO_TYPE_EFI;
695
696 si->lfb_width = width;
697 si->lfb_height = height;
698 si->lfb_base = fb_base;
699 si->pages = 1;
700
701 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
702
703 si->lfb_size = si->lfb_linelength * si->lfb_height;
704
705 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
706out:
707 return status;
708}
709
710static efi_status_t
711__gop_query64(struct efi_graphics_output_protocol_64 *gop64,
712 struct efi_graphics_output_mode_info **info,
713 unsigned long *size, u32 *fb_base)
714{
715 struct efi_graphics_output_protocol_mode_64 *mode;
716 efi_status_t status;
717 unsigned long m;
718
719 m = gop64->mode;
720 mode = (struct efi_graphics_output_protocol_mode_64 *)m;
721
722 status = efi_early->call(gop64->query_mode, gop64,
723 mode->mode, size, info);
322 if (status != EFI_SUCCESS) 724 if (status != EFI_SUCCESS)
323 return status; 725 return status;
324 726
325 status = efi_early->call(efi_early->locate_handle, 727 *fb_base = mode->frame_buffer_base;
326 EFI_LOCATE_BY_PROTOCOL, 728 return status;
327 proto, NULL, &size, gop_handle); 729}
328 if (status != EFI_SUCCESS) 730
329 goto free_handle; 731static efi_status_t
732setup_gop64(struct screen_info *si, efi_guid_t *proto,
733 unsigned long size, void **gop_handle)
734{
735 struct efi_graphics_output_protocol_64 *gop64, *first_gop;
736 unsigned long nr_gops;
737 u16 width, height;
738 u32 pixels_per_scan_line;
739 u32 fb_base;
740 struct efi_pixel_bitmask pixel_info;
741 int pixel_format;
742 efi_status_t status;
743 u64 *handles = (u64 *)(unsigned long)gop_handle;
744 int i;
330 745
331 first_gop = NULL; 746 first_gop = NULL;
747 gop64 = NULL;
332 748
333 nr_gops = size / sizeof(void *); 749 nr_gops = size / sizeof(u64);
334 for (i = 0; i < nr_gops; i++) { 750 for (i = 0; i < nr_gops; i++) {
335 struct efi_graphics_output_mode_info *info; 751 struct efi_graphics_output_mode_info *info = NULL;
336 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID; 752 efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
337 bool conout_found = false; 753 bool conout_found = false;
338 void *dummy; 754 void *dummy = NULL;
339 void *h = gop_handle[i]; 755 u64 h = handles[i];
340 756
341 status = efi_early->call(efi_early->handle_protocol, h, 757 status = efi_early->call(efi_early->handle_protocol, h,
342 proto, (void **)&gop); 758 proto, (void **)&gop64);
343 if (status != EFI_SUCCESS) 759 if (status != EFI_SUCCESS)
344 continue; 760 continue;
345 761
@@ -348,8 +764,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
348 if (status == EFI_SUCCESS) 764 if (status == EFI_SUCCESS)
349 conout_found = true; 765 conout_found = true;
350 766
351 status = efi_early->call((unsigned long)gop->query_mode, gop, 767 status = __gop_query64(gop64, &info, &size, &fb_base);
352 gop->mode->mode, &size, &info);
353 if (status == EFI_SUCCESS && (!first_gop || conout_found)) { 768 if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
354 /* 769 /*
355 * Systems that use the UEFI Console Splitter may 770 * Systems that use the UEFI Console Splitter may
@@ -360,8 +775,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
360 */ 775 */
361 width = info->horizontal_resolution; 776 width = info->horizontal_resolution;
362 height = info->vertical_resolution; 777 height = info->vertical_resolution;
363 fb_base = gop->mode->frame_buffer_base;
364 fb_size = gop->mode->frame_buffer_size;
365 pixel_format = info->pixel_format; 778 pixel_format = info->pixel_format;
366 pixel_info = info->pixel_information; 779 pixel_info = info->pixel_information;
367 pixels_per_scan_line = info->pixels_per_scan_line; 780 pixels_per_scan_line = info->pixels_per_scan_line;
@@ -370,7 +783,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
370 * Once we've found a GOP supporting ConOut, 783 * Once we've found a GOP supporting ConOut,
371 * don't bother looking any further. 784 * don't bother looking any further.
372 */ 785 */
373 first_gop = gop; 786 first_gop = gop64;
374 if (conout_found) 787 if (conout_found)
375 break; 788 break;
376 } 789 }
@@ -378,7 +791,7 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
378 791
379 /* Did we find any GOPs? */ 792 /* Did we find any GOPs? */
380 if (!first_gop) 793 if (!first_gop)
381 goto free_handle; 794 goto out;
382 795
383 /* EFI framebuffer */ 796 /* EFI framebuffer */
384 si->orig_video_isVGA = VIDEO_TYPE_EFI; 797 si->orig_video_isVGA = VIDEO_TYPE_EFI;
@@ -388,95 +801,111 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
388 si->lfb_base = fb_base; 801 si->lfb_base = fb_base;
389 si->pages = 1; 802 si->pages = 1;
390 803
391 if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) { 804 setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
392 si->lfb_depth = 32;
393 si->lfb_linelength = pixels_per_scan_line * 4;
394 si->red_size = 8;
395 si->red_pos = 0;
396 si->green_size = 8;
397 si->green_pos = 8;
398 si->blue_size = 8;
399 si->blue_pos = 16;
400 si->rsvd_size = 8;
401 si->rsvd_pos = 24;
402 } else if (pixel_format == PIXEL_BGR_RESERVED_8BIT_PER_COLOR) {
403 si->lfb_depth = 32;
404 si->lfb_linelength = pixels_per_scan_line * 4;
405 si->red_size = 8;
406 si->red_pos = 16;
407 si->green_size = 8;
408 si->green_pos = 8;
409 si->blue_size = 8;
410 si->blue_pos = 0;
411 si->rsvd_size = 8;
412 si->rsvd_pos = 24;
413 } else if (pixel_format == PIXEL_BIT_MASK) {
414 find_bits(pixel_info.red_mask, &si->red_pos, &si->red_size);
415 find_bits(pixel_info.green_mask, &si->green_pos,
416 &si->green_size);
417 find_bits(pixel_info.blue_mask, &si->blue_pos, &si->blue_size);
418 find_bits(pixel_info.reserved_mask, &si->rsvd_pos,
419 &si->rsvd_size);
420 si->lfb_depth = si->red_size + si->green_size +
421 si->blue_size + si->rsvd_size;
422 si->lfb_linelength = (pixels_per_scan_line * si->lfb_depth) / 8;
423 } else {
424 si->lfb_depth = 4;
425 si->lfb_linelength = si->lfb_width / 2;
426 si->red_size = 0;
427 si->red_pos = 0;
428 si->green_size = 0;
429 si->green_pos = 0;
430 si->blue_size = 0;
431 si->blue_pos = 0;
432 si->rsvd_size = 0;
433 si->rsvd_pos = 0;
434 }
435 805
436 si->lfb_size = si->lfb_linelength * si->lfb_height; 806 si->lfb_size = si->lfb_linelength * si->lfb_height;
437 807
438 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS; 808 si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
439 809out:
440free_handle:
441 efi_early->call(efi_early->free_pool, gop_handle);
442 return status; 810 return status;
443} 811}
444 812
445/* 813/*
446 * See if we have Universal Graphics Adapter (UGA) protocol 814 * See if we have Graphics Output Protocol
447 */ 815 */
448static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto, 816static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
449 unsigned long size) 817 unsigned long size)
450{ 818{
451 struct efi_uga_draw_protocol *uga, *first_uga;
452 unsigned long nr_ugas;
453 efi_status_t status; 819 efi_status_t status;
454 u32 width, height; 820 void **gop_handle = NULL;
455 void **uga_handle = NULL;
456 int i;
457 821
458 status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA, 822 status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
459 size, (void **)&uga_handle); 823 size, (void **)&gop_handle);
460 if (status != EFI_SUCCESS) 824 if (status != EFI_SUCCESS)
461 return status; 825 return status;
462 826
463 status = efi_early->call(efi_early->locate_handle, 827 status = efi_early->call(efi_early->locate_handle,
464 EFI_LOCATE_BY_PROTOCOL, 828 EFI_LOCATE_BY_PROTOCOL,
465 uga_proto, NULL, &size, uga_handle); 829 proto, NULL, &size, gop_handle);
466 if (status != EFI_SUCCESS) 830 if (status != EFI_SUCCESS)
467 goto free_handle; 831 goto free_handle;
468 832
833 if (efi_early->is64)
834 status = setup_gop64(si, proto, size, gop_handle);
835 else
836 status = setup_gop32(si, proto, size, gop_handle);
837
838free_handle:
839 efi_early->call(efi_early->free_pool, gop_handle);
840 return status;
841}
842
843static efi_status_t
844setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
845{
846 struct efi_uga_draw_protocol *uga = NULL, *first_uga;
847 efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
848 unsigned long nr_ugas;
849 u32 *handles = (u32 *)uga_handle;;
850 efi_status_t status;
851 int i;
852
469 first_uga = NULL; 853 first_uga = NULL;
854 nr_ugas = size / sizeof(u32);
855 for (i = 0; i < nr_ugas; i++) {
856 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
857 u32 w, h, depth, refresh;
858 void *pciio;
859 u32 handle = handles[i];
860
861 status = efi_early->call(efi_early->handle_protocol, handle,
862 &uga_proto, (void **)&uga);
863 if (status != EFI_SUCCESS)
864 continue;
865
866 efi_early->call(efi_early->handle_protocol, handle,
867 &pciio_proto, &pciio);
868
869 status = efi_early->call((unsigned long)uga->get_mode, uga,
870 &w, &h, &depth, &refresh);
871 if (status == EFI_SUCCESS && (!first_uga || pciio)) {
872 *width = w;
873 *height = h;
874
875 /*
876 * Once we've found a UGA supporting PCIIO,
877 * don't bother looking any further.
878 */
879 if (pciio)
880 break;
470 881
471 nr_ugas = size / sizeof(void *); 882 first_uga = uga;
883 }
884 }
885
886 return status;
887}
888
889static efi_status_t
890setup_uga64(void **uga_handle, unsigned long size, u32 *width, u32 *height)
891{
892 struct efi_uga_draw_protocol *uga = NULL, *first_uga;
893 efi_guid_t uga_proto = EFI_UGA_PROTOCOL_GUID;
894 unsigned long nr_ugas;
895 u64 *handles = (u64 *)uga_handle;;
896 efi_status_t status;
897 int i;
898
899 first_uga = NULL;
900 nr_ugas = size / sizeof(u64);
472 for (i = 0; i < nr_ugas; i++) { 901 for (i = 0; i < nr_ugas; i++) {
473 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID; 902 efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
474 void *handle = uga_handle[i];
475 u32 w, h, depth, refresh; 903 u32 w, h, depth, refresh;
476 void *pciio; 904 void *pciio;
905 u64 handle = handles[i];
477 906
478 status = efi_early->call(efi_early->handle_protocol, handle, 907 status = efi_early->call(efi_early->handle_protocol, handle,
479 uga_proto, (void **)&uga); 908 &uga_proto, (void **)&uga);
480 if (status != EFI_SUCCESS) 909 if (status != EFI_SUCCESS)
481 continue; 910 continue;
482 911
@@ -486,8 +915,8 @@ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
486 status = efi_early->call((unsigned long)uga->get_mode, uga, 915 status = efi_early->call((unsigned long)uga->get_mode, uga,
487 &w, &h, &depth, &refresh); 916 &w, &h, &depth, &refresh);
488 if (status == EFI_SUCCESS && (!first_uga || pciio)) { 917 if (status == EFI_SUCCESS && (!first_uga || pciio)) {
489 width = w; 918 *width = w;
490 height = h; 919 *height = h;
491 920
492 /* 921 /*
493 * Once we've found a UGA supporting PCIIO, 922 * Once we've found a UGA supporting PCIIO,
@@ -500,7 +929,39 @@ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
500 } 929 }
501 } 930 }
502 931
503 if (!first_uga) 932 return status;
933}
934
935/*
936 * See if we have Universal Graphics Adapter (UGA) protocol
937 */
938static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
939 unsigned long size)
940{
941 efi_status_t status;
942 u32 width, height;
943 void **uga_handle = NULL;
944
945 status = efi_early->call(efi_early->allocate_pool, EFI_LOADER_DATA,
946 size, (void **)&uga_handle);
947 if (status != EFI_SUCCESS)
948 return status;
949
950 status = efi_early->call(efi_early->locate_handle,
951 EFI_LOCATE_BY_PROTOCOL,
952 uga_proto, NULL, &size, uga_handle);
953 if (status != EFI_SUCCESS)
954 goto free_handle;
955
956 height = 0;
957 width = 0;
958
959 if (efi_early->is64)
960 status = setup_uga64(uga_handle, size, &width, &height);
961 else
962 status = setup_uga32(uga_handle, size, &width, &height);
963
964 if (!width && !height)
504 goto free_handle; 965 goto free_handle;
505 966
506 /* EFI framebuffer */ 967 /* EFI framebuffer */
@@ -519,7 +980,6 @@ static efi_status_t setup_uga(struct screen_info *si, efi_guid_t *uga_proto,
519 si->rsvd_size = 8; 980 si->rsvd_size = 8;
520 si->rsvd_pos = 24; 981 si->rsvd_pos = 24;
521 982
522
523free_handle: 983free_handle:
524 efi_early->call(efi_early->free_pool, uga_handle); 984 efi_early->call(efi_early->free_pool, uga_handle);
525 return status; 985 return status;