1 /*
2 * Architecture specific implementation for EFI boot code. This file
3 * is intended to be included by common/efi/boot.c _only_, and
4 * therefore can define arch specific global variables.
5 */
6 #include <xen/vga.h>
7 #include <asm/e820.h>
8 #include <asm/edd.h>
9 #include <asm/microcode.h>
10 #include <asm/msr.h>
11 #include <asm/setup.h>
12
13 static struct file __initdata ucode;
14 static multiboot_info_t __initdata mbi = {
15 .flags = MBI_MODULES | MBI_LOADERNAME
16 };
17 /*
18 * The array size needs to be one larger than the number of modules we
19 * support - see __start_xen().
20 */
21 static module_t __initdata mb_modules[5];
22
edd_put_string(u8 * dst,size_t n,const char * src)23 static void __init edd_put_string(u8 *dst, size_t n, const char *src)
24 {
25 while ( n-- && *src )
26 *dst++ = *src++;
27 if ( *src )
28 PrintErrMesg(L"Internal error populating EDD info",
29 EFI_BUFFER_TOO_SMALL);
30 while ( n-- )
31 *dst++ = ' ';
32 }
33 #define edd_put_string(d, s) edd_put_string(d, ARRAY_SIZE(d), s)
34
35 extern const intpte_t __page_tables_start[], __page_tables_end[];
36 #define in_page_tables(v) ((intpte_t *)(v) >= __page_tables_start && \
37 (intpte_t *)(v) < __page_tables_end)
38
39 #define PE_BASE_RELOC_ABS 0
40 #define PE_BASE_RELOC_HIGHLOW 3
41 #define PE_BASE_RELOC_DIR64 10
42
43 extern const struct pe_base_relocs {
44 u32 rva;
45 u32 size;
46 u16 entries[];
47 } __base_relocs_start[], __base_relocs_end[];
48
efi_arch_relocate_image(unsigned long delta)49 static void __init efi_arch_relocate_image(unsigned long delta)
50 {
51 const struct pe_base_relocs *base_relocs;
52
53 for ( base_relocs = __base_relocs_start; base_relocs < __base_relocs_end; )
54 {
55 unsigned int i = 0, n;
56
57 n = (base_relocs->size - sizeof(*base_relocs)) /
58 sizeof(*base_relocs->entries);
59
60 /*
61 * Relevant l{2,3}_bootmap entries get initialized explicitly in
62 * efi_arch_memory_setup(), so we must not apply relocations there.
63 * l2_directmap's first slot, otoh, should be handled normally, as
64 * efi_arch_memory_setup() won't touch it (xen_phys_start should
65 * never be zero).
66 */
67 if ( xen_phys_start + base_relocs->rva == (unsigned long)l3_bootmap ||
68 xen_phys_start + base_relocs->rva == (unsigned long)l2_bootmap )
69 i = n;
70
71 for ( ; i < n; ++i )
72 {
73 unsigned long addr = xen_phys_start + base_relocs->rva +
74 (base_relocs->entries[i] & 0xfff);
75
76 switch ( base_relocs->entries[i] >> 12 )
77 {
78 case PE_BASE_RELOC_ABS:
79 break;
80 case PE_BASE_RELOC_HIGHLOW:
81 if ( delta )
82 {
83 *(u32 *)addr += delta;
84 if ( in_page_tables(addr) )
85 *(u32 *)addr += xen_phys_start;
86 }
87 break;
88 case PE_BASE_RELOC_DIR64:
89 if ( delta )
90 {
91 *(u64 *)addr += delta;
92 if ( in_page_tables(addr) )
93 *(u64 *)addr += xen_phys_start;
94 }
95 break;
96 default:
97 blexit(L"Unsupported relocation type");
98 }
99 }
100 base_relocs = (const void *)(base_relocs->entries + i + (i & 1));
101 }
102 }
103
104 extern const s32 __trampoline_rel_start[], __trampoline_rel_stop[];
105 extern const s32 __trampoline_seg_start[], __trampoline_seg_stop[];
106
relocate_trampoline(unsigned long phys)107 static void __init relocate_trampoline(unsigned long phys)
108 {
109 const s32 *trampoline_ptr;
110
111 trampoline_phys = phys;
112
113 if ( !efi_enabled(EFI_LOADER) )
114 return;
115
116 /* Apply relocations to trampoline. */
117 for ( trampoline_ptr = __trampoline_rel_start;
118 trampoline_ptr < __trampoline_rel_stop;
119 ++trampoline_ptr )
120 *(u32 *)(*trampoline_ptr + (long)trampoline_ptr) += phys;
121 for ( trampoline_ptr = __trampoline_seg_start;
122 trampoline_ptr < __trampoline_seg_stop;
123 ++trampoline_ptr )
124 *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys >> 4;
125 }
126
place_string(u32 * addr,const char * s)127 static void __init place_string(u32 *addr, const char *s)
128 {
129 char *alloc = NULL;
130
131 if ( s && *s )
132 {
133 size_t len1 = strlen(s) + 1;
134 const char *old = (char *)(long)*addr;
135 size_t len2 = *addr ? strlen(old) + 1 : 0;
136
137 alloc = ebmalloc(len1 + len2);
138 /*
139 * Insert new string before already existing one. This is needed
140 * for options passed on the command line to override options from
141 * the configuration file.
142 */
143 memcpy(alloc, s, len1);
144 if ( *addr )
145 {
146 alloc[len1 - 1] = ' ';
147 memcpy(alloc + len1, old, len2);
148 }
149 }
150 *addr = (long)alloc;
151 }
152
efi_arch_process_memory_map(EFI_SYSTEM_TABLE * SystemTable,void * map,UINTN map_size,UINTN desc_size,UINT32 desc_ver)153 static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable,
154 void *map,
155 UINTN map_size,
156 UINTN desc_size,
157 UINT32 desc_ver)
158 {
159 struct e820entry *e;
160 unsigned int i;
161
162 /* Populate E820 table and check trampoline area availability. */
163 e = e820_raw.map - 1;
164 for ( e820_raw.nr_map = i = 0; i < map_size; i += desc_size )
165 {
166 EFI_MEMORY_DESCRIPTOR *desc = map + i;
167 u64 len = desc->NumberOfPages << EFI_PAGE_SHIFT;
168 u32 type;
169
170 switch ( desc->Type )
171 {
172 default:
173 type = E820_RESERVED;
174 break;
175
176 case EfiBootServicesCode:
177 case EfiBootServicesData:
178 if ( map_bs )
179 {
180 type = E820_RESERVED;
181 break;
182 }
183 fallthrough;
184 case EfiConventionalMemory:
185 if ( !trampoline_phys && desc->PhysicalStart + len <= 0x100000 &&
186 len >= cfg.size && desc->PhysicalStart + len > cfg.addr )
187 cfg.addr = (desc->PhysicalStart + len - cfg.size) & PAGE_MASK;
188 fallthrough;
189 case EfiLoaderCode:
190 case EfiLoaderData:
191 if ( desc->Attribute & EFI_MEMORY_RUNTIME )
192 type = E820_RESERVED;
193 else if ( desc->Attribute & EFI_MEMORY_WB )
194 type = E820_RAM;
195 else
196 type = E820_UNUSABLE;
197 break;
198
199 case EfiUnusableMemory:
200 type = E820_UNUSABLE;
201 break;
202
203 case EfiACPIReclaimMemory:
204 type = E820_ACPI;
205 break;
206 case EfiACPIMemoryNVS:
207 type = E820_NVS;
208 break;
209 }
210 if ( e820_raw.nr_map && type == e->type &&
211 desc->PhysicalStart == e->addr + e->size )
212 e->size += len;
213 else if ( !len || e820_raw.nr_map >= ARRAY_SIZE(e820_raw.map) )
214 continue;
215 else
216 {
217 ++e;
218 e->addr = desc->PhysicalStart;
219 e->size = len;
220 e->type = type;
221 ++e820_raw.nr_map;
222 }
223 }
224
225 }
226
efi_arch_allocate_mmap_buffer(UINTN map_size)227 static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size)
228 {
229 return ebmalloc(map_size);
230 }
231
efi_arch_pre_exit_boot(void)232 static void __init efi_arch_pre_exit_boot(void)
233 {
234 if ( !trampoline_phys )
235 {
236 if ( !cfg.addr )
237 blexit(L"No memory for trampoline");
238 relocate_trampoline(cfg.addr);
239 }
240 }
241
efi_arch_post_exit_boot(void)242 static void __init noreturn efi_arch_post_exit_boot(void)
243 {
244 u64 cr4 = XEN_MINIMAL_CR4 & ~X86_CR4_PGE, efer;
245
246 efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start);
247 memcpy((void *)trampoline_phys, trampoline_start, cfg.size);
248
249 /* Set system registers and transfer control. */
250 asm volatile("pushq $0\n\tpopfq");
251 rdmsrl(MSR_EFER, efer);
252 efer |= trampoline_efer;
253 wrmsrl(MSR_EFER, efer);
254 wrmsrl(MSR_IA32_CR_PAT, XEN_MSR_PAT);
255 write_cr0(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP |
256 X86_CR0_AM | X86_CR0_PG);
257 asm volatile ( "mov %[cr4], %%cr4\n\t"
258 "mov %[cr3], %%cr3\n\t"
259 #if XEN_MINIMAL_CR4 & X86_CR4_PGE
260 "or $"__stringify(X86_CR4_PGE)", %[cr4]\n\t"
261 "mov %[cr4], %%cr4\n\t"
262 #endif
263 "lgdt boot_gdtr(%%rip)\n\t"
264 "mov %[ds], %%ss\n\t"
265 "mov %[ds], %%ds\n\t"
266 "mov %[ds], %%es\n\t"
267 "mov %[ds], %%fs\n\t"
268 "mov %[ds], %%gs\n\t"
269
270 /* Jump to higher mappings. */
271 "mov stack_start(%%rip), %%rsp\n\t"
272 "movabs $__start_xen, %[rip]\n\t"
273 "push %[cs]\n\t"
274 "push %[rip]\n\t"
275 "lretq"
276 : [rip] "=&r" (efer/* any dead 64-bit variable */),
277 [cr4] "+&r" (cr4)
278 : [cr3] "r" (idle_pg_table),
279 [cs] "i" (__HYPERVISOR_CS),
280 [ds] "r" (__HYPERVISOR_DS),
281 "D" (&mbi)
282 : "memory" );
283 unreachable();
284 }
285
efi_arch_cfg_file_early(const EFI_LOADED_IMAGE * image,EFI_FILE_HANDLE dir_handle,const char * section)286 static void __init efi_arch_cfg_file_early(const EFI_LOADED_IMAGE *image,
287 EFI_FILE_HANDLE dir_handle,
288 const char *section)
289 {
290 }
291
efi_arch_cfg_file_late(const EFI_LOADED_IMAGE * image,EFI_FILE_HANDLE dir_handle,const char * section)292 static void __init efi_arch_cfg_file_late(const EFI_LOADED_IMAGE *image,
293 EFI_FILE_HANDLE dir_handle,
294 const char *section)
295 {
296 union string name;
297
298 if ( read_section(image, L"ucode", &ucode, NULL) )
299 return;
300
301 name.s = get_value(&cfg, section, "ucode");
302 if ( !name.s )
303 name.s = get_value(&cfg, "global", "ucode");
304 if ( name.s )
305 {
306 microcode_set_module(mbi.mods_count);
307 split_string(name.s);
308 read_file(dir_handle, s2w(&name), &ucode, NULL);
309 efi_bs->FreePool(name.w);
310 }
311 }
312
efi_arch_handle_cmdline(CHAR16 * cmdline_options,const char * cfgfile_options)313 static void __init efi_arch_handle_cmdline(CHAR16 *cmdline_options,
314 const char *cfgfile_options)
315 {
316 union string name;
317
318 /* NB place_string() prepends, so call in reverse order. */
319 if ( cmdline_options )
320 {
321 name.w = cmdline_options;
322 w2s(&name);
323 place_string(&mbi.cmdline, name.s);
324 }
325 if ( cfgfile_options )
326 place_string(&mbi.cmdline, cfgfile_options);
327
328 if ( mbi.cmdline )
329 mbi.flags |= MBI_CMDLINE;
330 /*
331 * These must not be initialized statically, since the value must
332 * not get relocated when processing base relocations later.
333 */
334 mbi.boot_loader_name = (long)"EFI";
335 mbi.mods_addr = (long)mb_modules;
336 }
337
efi_arch_edd(void)338 static void __init efi_arch_edd(void)
339 {
340 static EFI_GUID __initdata bio_guid = BLOCK_IO_PROTOCOL;
341 static EFI_GUID __initdata devp_guid = DEVICE_PATH_PROTOCOL;
342 EFI_HANDLE *handles = NULL;
343 unsigned int i;
344 UINTN size;
345 EFI_STATUS status;
346
347 /* Collect EDD info. */
348 BUILD_BUG_ON(offsetof(struct edd_info, edd_device_params) != EDDEXTSIZE);
349 BUILD_BUG_ON(sizeof(struct edd_device_params) != EDDPARMSIZE);
350 size = 0;
351 status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size, NULL);
352 if ( status == EFI_BUFFER_TOO_SMALL )
353 status = efi_bs->AllocatePool(EfiLoaderData, size, (void **)&handles);
354 if ( !EFI_ERROR(status) )
355 status = efi_bs->LocateHandle(ByProtocol, &bio_guid, NULL, &size,
356 handles);
357 if ( EFI_ERROR(status) )
358 size = 0;
359 for ( i = 0; i < size / sizeof(*handles); ++i )
360 {
361 EFI_BLOCK_IO *bio;
362 EFI_DEV_PATH_PTR devp;
363 struct edd_info *info = boot_edd_info + boot_edd_info_nr;
364 struct edd_device_params *params = &info->edd_device_params;
365 enum { root, acpi, pci, ctrlr } state = root;
366
367 status = efi_bs->HandleProtocol(handles[i], &bio_guid, (void **)&bio);
368 if ( EFI_ERROR(status) ||
369 bio->Media->RemovableMedia ||
370 bio->Media->LogicalPartition )
371 continue;
372 if ( boot_edd_info_nr < EDD_INFO_MAX )
373 {
374 info->device = 0x80 + boot_edd_info_nr; /* fake */
375 info->version = 0x11;
376 params->length = offsetof(struct edd_device_params, dpte_ptr);
377 params->number_of_sectors = bio->Media->LastBlock + 1;
378 params->bytes_per_sector = bio->Media->BlockSize;
379 params->dpte_ptr = ~0;
380 }
381 ++boot_edd_info_nr;
382 status = efi_bs->HandleProtocol(handles[i], &devp_guid,
383 (void **)&devp);
384 if ( EFI_ERROR(status) )
385 continue;
386 for ( ; !IsDevicePathEnd(devp.DevPath);
387 devp.DevPath = NextDevicePathNode(devp.DevPath) )
388 {
389 switch ( DevicePathType(devp.DevPath) )
390 {
391 const u8 *p;
392
393 case ACPI_DEVICE_PATH:
394 if ( state != root || boot_edd_info_nr > EDD_INFO_MAX )
395 break;
396 switch ( DevicePathSubType(devp.DevPath) )
397 {
398 case ACPI_DP:
399 if ( devp.Acpi->HID != EISA_PNP_ID(0xA03) &&
400 devp.Acpi->HID != EISA_PNP_ID(0xA08) )
401 break;
402 params->interface_path.pci.bus = devp.Acpi->UID;
403 state = acpi;
404 break;
405 case EXPANDED_ACPI_DP:
406 /* XXX */
407 break;
408 }
409 break;
410 case HARDWARE_DEVICE_PATH:
411 if ( state != acpi ||
412 DevicePathSubType(devp.DevPath) != HW_PCI_DP ||
413 boot_edd_info_nr > EDD_INFO_MAX )
414 break;
415 state = pci;
416 edd_put_string(params->host_bus_type, "PCI");
417 params->interface_path.pci.slot = devp.Pci->Device;
418 params->interface_path.pci.function = devp.Pci->Function;
419 break;
420 case MESSAGING_DEVICE_PATH:
421 if ( state != pci || boot_edd_info_nr > EDD_INFO_MAX )
422 break;
423 state = ctrlr;
424 switch ( DevicePathSubType(devp.DevPath) )
425 {
426 case MSG_ATAPI_DP:
427 edd_put_string(params->interface_type, "ATAPI");
428 params->interface_path.pci.channel =
429 devp.Atapi->PrimarySecondary;
430 params->device_path.atapi.device = devp.Atapi->SlaveMaster;
431 params->device_path.atapi.lun = devp.Atapi->Lun;
432 break;
433 case MSG_SCSI_DP:
434 edd_put_string(params->interface_type, "SCSI");
435 params->device_path.scsi.id = devp.Scsi->Pun;
436 params->device_path.scsi.lun = devp.Scsi->Lun;
437 break;
438 case MSG_FIBRECHANNEL_DP:
439 edd_put_string(params->interface_type, "FIBRE");
440 params->device_path.fibre.wwid = devp.FibreChannel->WWN;
441 params->device_path.fibre.lun = devp.FibreChannel->Lun;
442 break;
443 case MSG_1394_DP:
444 edd_put_string(params->interface_type, "1394");
445 params->device_path.i1394.eui = devp.F1394->Guid;
446 break;
447 case MSG_USB_DP:
448 case MSG_USB_CLASS_DP:
449 edd_put_string(params->interface_type, "USB");
450 break;
451 case MSG_I2O_DP:
452 edd_put_string(params->interface_type, "I2O");
453 params->device_path.i2o.identity_tag = devp.I2O->Tid;
454 break;
455 default:
456 continue;
457 }
458 info->version = 0x30;
459 params->length = sizeof(struct edd_device_params);
460 params->key = 0xbedd;
461 params->device_path_info_length =
462 sizeof(struct edd_device_params) -
463 offsetof(struct edd_device_params, key);
464 for ( p = (const u8 *)¶ms->key; p < ¶ms->checksum; ++p )
465 params->checksum -= *p;
466 break;
467 case MEDIA_DEVICE_PATH:
468 if ( DevicePathSubType(devp.DevPath) == MEDIA_HARDDRIVE_DP &&
469 devp.HardDrive->MBRType == MBR_TYPE_PCAT &&
470 boot_mbr_signature_nr < EDD_MBR_SIG_MAX )
471 {
472 struct mbr_signature *sig = boot_mbr_signature +
473 boot_mbr_signature_nr;
474
475 sig->device = 0x80 + boot_edd_info_nr; /* fake */
476 memcpy(&sig->signature, devp.HardDrive->Signature,
477 sizeof(sig->signature));
478 ++boot_mbr_signature_nr;
479 }
480 break;
481 }
482 }
483 }
484 if ( handles )
485 efi_bs->FreePool(handles);
486 if ( boot_edd_info_nr > EDD_INFO_MAX )
487 boot_edd_info_nr = EDD_INFO_MAX;
488 }
489
efi_arch_console_init(UINTN cols,UINTN rows)490 static void __init efi_arch_console_init(UINTN cols, UINTN rows)
491 {
492 #ifdef CONFIG_VIDEO
493 vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
494 vga_console_info.u.text_mode_3.columns = cols;
495 vga_console_info.u.text_mode_3.rows = rows;
496 vga_console_info.u.text_mode_3.font_height = 16;
497 #endif
498 }
499
efi_arch_video_init(EFI_GRAPHICS_OUTPUT_PROTOCOL * gop,UINTN info_size,EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * mode_info)500 static void __init efi_arch_video_init(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop,
501 UINTN info_size,
502 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info)
503 {
504 #ifdef CONFIG_VIDEO
505 int bpp = 0;
506
507 if ( !gop->Mode->FrameBufferBase || !mode_info->HorizontalResolution ||
508 !mode_info->VerticalResolution )
509 {
510 PrintErr(L"Invalid Frame Buffer configuration found\r\n");
511 return;
512 }
513
514 switch ( mode_info->PixelFormat )
515 {
516 case PixelRedGreenBlueReserved8BitPerColor:
517 vga_console_info.u.vesa_lfb.red_pos = 0;
518 vga_console_info.u.vesa_lfb.red_size = 8;
519 vga_console_info.u.vesa_lfb.green_pos = 8;
520 vga_console_info.u.vesa_lfb.green_size = 8;
521 vga_console_info.u.vesa_lfb.blue_pos = 16;
522 vga_console_info.u.vesa_lfb.blue_size = 8;
523 vga_console_info.u.vesa_lfb.rsvd_pos = 24;
524 vga_console_info.u.vesa_lfb.rsvd_size = 8;
525 bpp = 32;
526 break;
527 case PixelBlueGreenRedReserved8BitPerColor:
528 vga_console_info.u.vesa_lfb.red_pos = 16;
529 vga_console_info.u.vesa_lfb.red_size = 8;
530 vga_console_info.u.vesa_lfb.green_pos = 8;
531 vga_console_info.u.vesa_lfb.green_size = 8;
532 vga_console_info.u.vesa_lfb.blue_pos = 0;
533 vga_console_info.u.vesa_lfb.blue_size = 8;
534 vga_console_info.u.vesa_lfb.rsvd_pos = 24;
535 vga_console_info.u.vesa_lfb.rsvd_size = 8;
536 bpp = 32;
537 break;
538 case PixelBitMask:
539 bpp = set_color(mode_info->PixelInformation.RedMask, bpp,
540 &vga_console_info.u.vesa_lfb.red_pos,
541 &vga_console_info.u.vesa_lfb.red_size);
542 bpp = set_color(mode_info->PixelInformation.GreenMask, bpp,
543 &vga_console_info.u.vesa_lfb.green_pos,
544 &vga_console_info.u.vesa_lfb.green_size);
545 bpp = set_color(mode_info->PixelInformation.BlueMask, bpp,
546 &vga_console_info.u.vesa_lfb.blue_pos,
547 &vga_console_info.u.vesa_lfb.blue_size);
548 if ( mode_info->PixelInformation.ReservedMask )
549 bpp = set_color(mode_info->PixelInformation.ReservedMask, bpp,
550 &vga_console_info.u.vesa_lfb.rsvd_pos,
551 &vga_console_info.u.vesa_lfb.rsvd_size);
552 if ( bpp > 0 )
553 break;
554 /* fall through */
555 default:
556 PrintErr(L"Current graphics mode is unsupported!\r\n");
557 bpp = 0;
558 break;
559 }
560 if ( bpp > 0 )
561 {
562 vga_console_info.video_type = XEN_VGATYPE_EFI_LFB;
563 vga_console_info.u.vesa_lfb.gbl_caps = 2; /* possibly non-VGA */
564 vga_console_info.u.vesa_lfb.width =
565 mode_info->HorizontalResolution;
566 vga_console_info.u.vesa_lfb.height = mode_info->VerticalResolution;
567 vga_console_info.u.vesa_lfb.bits_per_pixel = bpp;
568 vga_console_info.u.vesa_lfb.bytes_per_line =
569 (mode_info->PixelsPerScanLine * bpp + 7) >> 3;
570 vga_console_info.u.vesa_lfb.lfb_base = gop->Mode->FrameBufferBase;
571 vga_console_info.u.vesa_lfb.ext_lfb_base = gop->Mode->FrameBufferBase >> 32;
572 vga_console_info.u.vesa_lfb.lfb_size =
573 (gop->Mode->FrameBufferSize + 0xffff) >> 16;
574 }
575 #endif
576 }
577
578 #ifdef CONFIG_VIDEO
copy_edid(const void * buf,unsigned int size)579 static bool __init copy_edid(const void *buf, unsigned int size)
580 {
581 /*
582 * Be conservative - for both undersized and oversized blobs it is unclear
583 * what to actually do with them. The more that unlike the VESA BIOS
584 * interface we also have no associated "capabilities" value (which might
585 * carry a hint as to possible interpretation).
586 */
587 if ( size != ARRAY_SIZE(boot_edid_info) )
588 return false;
589
590 memcpy(boot_edid_info, buf, size);
591 boot_edid_caps = 0;
592
593 return true;
594 }
595 #endif
596
efi_arch_edid(EFI_HANDLE gop_handle)597 static void __init efi_arch_edid(EFI_HANDLE gop_handle)
598 {
599 #ifdef CONFIG_VIDEO
600 static EFI_GUID __initdata active_guid = EFI_EDID_ACTIVE_PROTOCOL_GUID;
601 static EFI_GUID __initdata discovered_guid = EFI_EDID_DISCOVERED_PROTOCOL_GUID;
602 EFI_EDID_ACTIVE_PROTOCOL *active_edid;
603 EFI_EDID_DISCOVERED_PROTOCOL *discovered_edid;
604 EFI_STATUS status;
605
606 status = efi_bs->OpenProtocol(gop_handle, &active_guid,
607 (void **)&active_edid, efi_ih, NULL,
608 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
609 if ( status == EFI_SUCCESS &&
610 copy_edid(active_edid->Edid, active_edid->SizeOfEdid) )
611 return;
612
613 /*
614 * In case an override is in place which doesn't fit copy_edid(), also try
615 * obtaining the discovered EDID in the hope that it's better than nothing.
616 *
617 * Note that attempting to use the information in
618 * EFI_EDID_DISCOVERED_PROTOCOL when there's an override provided by
619 * EFI_EDID_ACTIVE_PROTOCOL might lead to issues.
620 */
621 status = efi_bs->OpenProtocol(gop_handle, &discovered_guid,
622 (void **)&discovered_edid, efi_ih, NULL,
623 EFI_OPEN_PROTOCOL_GET_PROTOCOL);
624 if ( status == EFI_SUCCESS )
625 copy_edid(discovered_edid->Edid, discovered_edid->SizeOfEdid);
626 #endif
627 }
628
efi_arch_memory_setup(void)629 static void __init efi_arch_memory_setup(void)
630 {
631 unsigned int i;
632 EFI_STATUS status;
633
634 /* Allocate space for trampoline (in first Mb). */
635 cfg.addr = 0x100000;
636
637 if ( efi_enabled(EFI_LOADER) )
638 cfg.size = trampoline_end - trampoline_start;
639 else
640 cfg.size = TRAMPOLINE_SPACE + TRAMPOLINE_STACK_SPACE;
641
642 status = efi_bs->AllocatePages(AllocateMaxAddress, EfiLoaderData,
643 PFN_UP(cfg.size), &cfg.addr);
644 if ( status == EFI_SUCCESS )
645 relocate_trampoline(cfg.addr);
646 else
647 {
648 cfg.addr = 0;
649 PrintStr(L"Trampoline space cannot be allocated; will try fallback.\r\n");
650 }
651
652 if ( !efi_enabled(EFI_LOADER) )
653 return;
654
655 /*
656 * Map Xen into the higher mappings, using 2M superpages.
657 *
658 * NB: We are currently in physical mode, so a RIP-relative relocation
659 * against _start/_end result in our arbitrary placement by the bootloader
660 * in memory, rather than the intended high mappings position. Subtract
661 * xen_phys_start to get the appropriate slots in l2_xenmap[].
662 */
663 for ( i = l2_table_offset((UINTN)_start - xen_phys_start);
664 i <= l2_table_offset((UINTN)_end - 1 - xen_phys_start); ++i )
665 l2_xenmap[i] =
666 l2e_from_paddr(xen_phys_start + (i << L2_PAGETABLE_SHIFT),
667 PAGE_HYPERVISOR_RWX | _PAGE_PSE);
668
669 /* Check that there is at least 4G of mapping space in l2_*map[] */
670 BUILD_BUG_ON((sizeof(l2_bootmap) / L2_PAGETABLE_ENTRIES) < 4);
671 BUILD_BUG_ON((sizeof(l2_directmap) / L2_PAGETABLE_ENTRIES) < 4);
672
673 /* Initialize L3 boot-map page directory entries. */
674 for ( i = 0; i < 4; ++i )
675 l3_bootmap[i] = l3e_from_paddr((UINTN)l2_bootmap + i * PAGE_SIZE,
676 __PAGE_HYPERVISOR);
677 /*
678 * Map Xen into the directmap (needed for early-boot pagetable
679 * handling/walking), and identity map Xen into bootmap (needed for the
680 * transition from the EFI pagetables to Xen), using 2M superpages.
681 *
682 * NB: We are currently in physical mode, so a RIP-relative relocation
683 * against _start/_end gets their real position in memory, which are the
684 * appropriate l2 slots to map.
685 */
686 #define l2_4G_offset(a) \
687 (((a) >> L2_PAGETABLE_SHIFT) & (4 * L2_PAGETABLE_ENTRIES - 1))
688
689 for ( i = l2_4G_offset((UINTN)_start);
690 i <= l2_4G_offset((UINTN)_end - 1); ++i )
691 {
692 l2_pgentry_t pte = l2e_from_paddr(i << L2_PAGETABLE_SHIFT,
693 __PAGE_HYPERVISOR | _PAGE_PSE);
694
695 l2_bootmap[i] = pte;
696
697 /* Bootmap RWX/Non-global. Directmap RW/Global. */
698 l2e_add_flags(pte, PAGE_HYPERVISOR);
699
700 l2_directmap[i] = pte;
701 }
702 #undef l2_4G_offset
703 }
704
efi_arch_handle_module(const struct file * file,const CHAR16 * name,const char * options)705 static void __init efi_arch_handle_module(const struct file *file,
706 const CHAR16 *name,
707 const char *options)
708 {
709 union string local_name;
710 void *ptr;
711
712 /*
713 * Make a copy, as conversion is destructive, and caller still wants
714 * wide string available after this call returns.
715 */
716 if ( efi_bs->AllocatePool(EfiLoaderData, (wstrlen(name) + 1) * sizeof(*name),
717 &ptr) != EFI_SUCCESS )
718 blexit(L"Unable to allocate string buffer");
719
720 local_name.w = ptr;
721 wstrcpy(local_name.w, name);
722 w2s(&local_name);
723
724 /*
725 * If options are provided, put them in
726 * mb_modules[mbi.mods_count].string after the filename, with a space
727 * separating them. place_string() prepends strings and adds separating
728 * spaces, so the call order is reversed.
729 */
730 if ( options )
731 place_string(&mb_modules[mbi.mods_count].string, options);
732 place_string(&mb_modules[mbi.mods_count].string, local_name.s);
733 mb_modules[mbi.mods_count].mod_start = file->addr >> PAGE_SHIFT;
734 mb_modules[mbi.mods_count].mod_end = file->size;
735 ++mbi.mods_count;
736 efi_bs->FreePool(ptr);
737 }
738
efi_arch_cpu(void)739 static void __init efi_arch_cpu(void)
740 {
741 uint32_t eax = cpuid_eax(0x80000000U);
742 uint32_t *caps = boot_cpu_data.x86_capability;
743
744 boot_tsc_stamp = rdtsc();
745
746 caps[FEATURESET_1c] = cpuid_ecx(1);
747
748 if ( (eax >> 16) == 0x8000 && eax > 0x80000000U )
749 {
750 caps[FEATURESET_e1d] = cpuid_edx(0x80000001U);
751
752 /*
753 * This check purposefully doesn't use cpu_has_nx because
754 * cpu_has_nx bypasses the boot_cpu_data read if Xen was compiled
755 * with CONFIG_REQUIRE_NX
756 */
757 if ( IS_ENABLED(CONFIG_REQUIRE_NX) &&
758 !boot_cpu_has(X86_FEATURE_NX) )
759 blexit(L"This build of Xen requires NX support");
760
761 if ( cpu_has_nx )
762 trampoline_efer |= EFER_NXE;
763 }
764 }
765
efi_arch_blexit(void)766 static void __init efi_arch_blexit(void)
767 {
768 if ( ucode.need_to_free )
769 efi_bs->FreePages(ucode.addr, PFN_UP(ucode.size));
770 }
771
efi_arch_halt(void)772 static void __init efi_arch_halt(void)
773 {
774 local_irq_disable();
775 for ( ; ; )
776 halt();
777 }
778
efi_arch_load_addr_check(const EFI_LOADED_IMAGE * loaded_image)779 static void __init efi_arch_load_addr_check(const EFI_LOADED_IMAGE *loaded_image)
780 {
781 xen_phys_start = (UINTN)loaded_image->ImageBase;
782 if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 )
783 blexit(L"Xen must be loaded below 4Gb.");
784 if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) )
785 blexit(L"Xen must be loaded at a 2Mb boundary.");
786 trampoline_xen_phys_start = xen_phys_start;
787 }
788
efi_arch_use_config_file(EFI_SYSTEM_TABLE * SystemTable)789 static bool __init efi_arch_use_config_file(EFI_SYSTEM_TABLE *SystemTable)
790 {
791 return true; /* x86 always uses a config file */
792 }
793
efi_arch_flush_dcache_area(const void * vaddr,UINTN size)794 static void __init efi_arch_flush_dcache_area(const void *vaddr, UINTN size) { }
795
796 /* Return a pointer to the character after the first occurrence of opt in cmd */
get_option(const char * cmd,const char * opt)797 static const char *__init get_option(const char *cmd, const char *opt)
798 {
799 const char *s = cmd, *o = NULL;
800
801 if ( !cmd || !opt )
802 return NULL;
803
804 while ( (s = strstr(s, opt)) != NULL )
805 {
806 if ( s == cmd || *(s - 1) == ' ' || *(s - 1) == '\t' )
807 {
808 o = s + strlen(opt);
809 break;
810 }
811
812 s += strlen(opt);
813 }
814
815 return o;
816 }
817
efi_multiboot2(EFI_HANDLE ImageHandle,EFI_SYSTEM_TABLE * SystemTable,const char * cmdline)818 void asmlinkage __init efi_multiboot2(EFI_HANDLE ImageHandle,
819 EFI_SYSTEM_TABLE *SystemTable,
820 const char *cmdline)
821 {
822 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
823 EFI_HANDLE gop_handle;
824 UINTN cols, gop_mode = ~0, rows;
825
826 __set_bit(EFI_BOOT, &efi_flags);
827 __set_bit(EFI_RS, &efi_flags);
828
829 efi_init(ImageHandle, SystemTable);
830
831 if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
832 &cols, &rows) != EFI_SUCCESS )
833 /*
834 * If active StdOut mode is invalid init ConOut (StdOut) to the max
835 * supported size.
836 */
837 efi_console_set_mode();
838
839 if ( StdOut->QueryMode(StdOut, StdOut->Mode->Mode,
840 &cols, &rows) == EFI_SUCCESS )
841 efi_arch_console_init(cols, rows);
842
843 gop = efi_get_gop(&gop_handle);
844
845 if ( gop )
846 {
847 const char *cur = cmdline;
848 unsigned int width = 0, height = 0, depth = 0;
849 bool keep_current = false;
850
851 while ( (cur = get_option(cur, "vga=")) != NULL )
852 {
853 #define VALID_TERMINATOR(c) \
854 (*(c) == ' ' || *(c) == '\t' || *(c) == '\0' || *(c) == ',')
855 if ( !strncmp(cur, "gfx-", 4) )
856 {
857 width = simple_strtoul(cur + 4, &cur, 10);
858
859 if ( *cur == 'x' )
860 height = simple_strtoul(cur + 1, &cur, 10);
861 else
862 goto error;
863
864 if ( *cur == 'x' )
865 depth = simple_strtoul(cur + 1, &cur, 10);
866 else
867 goto error;
868
869 if ( !VALID_TERMINATOR(cur) )
870 {
871 error:
872 PrintErr(L"Warning: Invalid gfx- option detected\r\n");
873 width = height = depth = 0;
874 }
875 keep_current = false;
876 }
877 else if ( !strncmp(cur, "current", 7) && VALID_TERMINATOR(cur + 7) )
878 keep_current = true;
879 else if ( !strncmp(cur, "keep", 4) && VALID_TERMINATOR(cur + 4) )
880 {
881 /* Ignore, handled in later vga= parsing. */
882 }
883 else
884 {
885 /* Fallback to defaults if unimplemented. */
886 width = height = depth = 0;
887 keep_current = false;
888 PrintErr(L"Warning: Cannot use selected vga option\r\n");
889 }
890 #undef VALID_TERMINATOR
891 }
892
893 if ( !keep_current )
894 gop_mode = efi_find_gop_mode(gop, width, height, depth);
895
896 efi_arch_edid(gop_handle);
897 }
898
899 efi_arch_edd();
900 efi_arch_cpu();
901
902 efi_tables();
903 setup_efi_pci();
904 efi_variables();
905 efi_arch_memory_setup();
906
907 if ( gop )
908 efi_set_gop_mode(gop, gop_mode);
909
910 efi_relocate_esrt(SystemTable);
911
912 efi_exit_boot(ImageHandle, SystemTable);
913 }
914
915 /*
916 * Local variables:
917 * mode: C
918 * c-file-style: "BSD"
919 * c-basic-offset: 4
920 * indent-tabs-mode: nil
921 * End:
922 */
923