2 * Copyright (C) 2001-2003 Hewlett-Packard Co.
3 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
4 * Contributed by Mike Johnston <johnston@intel.com>
5 * Contributed by Chris Ahna <christopher.j.ahna@intel.com>
6 * Contributed by Fenghua Yu <fenghua.yu@intel.com>
7 * Contributed by Bibo Mao <bibo.mao@intel.com>
8 * Contributed by chandramouli narayanan <mouli@linux.intel.com>
9 * Edgar Hucek <hostmaster@ed-soft.at>
11 * Updated with code to fill bootparam converting EFI memory map to E820
12 * based on a Linux kernel patch provided by Edgar Hucek
15 * This file is part of the ELILO, the EFI Linux boot loader.
17 * ELILO is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2, or (at your option)
22 * ELILO is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with ELILO; see the file COPYING. If not, write to the Free
29 * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
32 * Please check out the elilo.txt for complete documentation on how
33 * to use this program.
37 * This file contains all the x86_64 specific code expected by generic loader
47 #define DEBUG_CREATE_BOOT_PARAMS 0
48 #if DEBUG_CREATE_BOOT_PARAMS
49 #define DPR(a) do { if (elilo_opt.debug) { Print a; } } while ( 0 )
54 extern loader_ops_t bzimage_loader, plain_loader, gzip_loader;
57 * Descriptor table base addresses & limits for Linux startup.
60 dt_addr_t gdt_addr = { 0x800, 0x94000 };
61 dt_addr_t idt_addr = { 0, 0 };
64 * Initial GDT layout for Linux startup.
75 0xFFFF, /* 4Gb - (0x100000*0x1000 = 4Gb) */
76 0x0000, /* base address=0 */
77 0x9A00, /* code read/exec */
78 0x00CF, /* granularity=4096, 386 (+5th nibble of limit) */
81 0xFFFF, /* 4Gb - (0x100000*0x1000 = 4Gb) */
82 0x0000, /* base address=0 */
83 0x9200, /* data read/write */
84 0x00CF, /* granularity=4096, 386 (+5th nibble of limit) */
87 UINTN sizeof_init_gdt = sizeof init_gdt;
90 * Highest available base memory address.
92 * For traditional kernels and loaders this is always at 0x90000.
93 * For updated kernels and loaders this is computed by taking the
94 * highest available base memory address and rounding down to the
95 * nearest 64 kB boundary and then subtracting 64 kB.
97 * A non-compressed kernel is automatically assumed to be an updated
98 * kernel. A compressed kernel that has bit 6 (0x40) set in the
99 * loader_flags field is also assumed to be an updated kernel.
102 UINTN high_base_mem = 0x90000;
105 * Highest available extended memory address.
107 * This is computed by taking the highest available extended memory
108 * address and rounding down to the nearest EFI_PAGE_SIZE (usually
110 * This is only used for backward compatibility.
113 UINTN high_ext_mem = 32 * 1024 * 1024;
115 /* This starting address will hold true for all of the loader types for now */
116 VOID *kernel_start = (VOID *)DEFAULT_KERNEL_START;
118 /* The kernel may load elsewhere if EFI firmware reserves kernel_start */
119 VOID *kernel_load_address = (VOID *)DEFAULT_KERNEL_START;
121 VOID *initrd_start = NULL;
122 UINTN initrd_size = 0;
124 INTN e820_map_overflow = 0;
127 sysdeps_init(EFI_HANDLE dev)
129 DBG_PRT((L"sysdeps_init()\n"));
132 * Register our loader(s)...
135 loader_register(&bzimage_loader);
136 loader_register(&plain_loader);
137 loader_register(&gzip_loader);
143 * Compute a starting address for the initial RAMdisk image.
144 * For now we suggest 'initrd_addr_max' with room for 32MB,
145 * as image->pgcnt is not initialized yet.
148 sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem)
150 DBG_PRT((L"initrd_get_addr()\n"));
153 ERR_PRT((L"kd="PTR_FMT" imem="PTR_FMT"", kd, imem));
157 VERB_PRT(3, Print(L"initrd_addr_max="PTR_FMT" reserve=%d\n",
158 param_start->s.initrd_addr_max, 32*MB));
160 imem->start_addr = (VOID *)
161 (((UINT64)param_start->s.initrd_addr_max - 32*MB + 1)
164 VERB_PRT(3, Print(L"initrd start_addr="PTR_FMT" pgcnt=%d\n",
165 imem->start_addr, imem->pgcnt));
173 * Check and possibly fix allocation of initrd memory.
176 sysdeps_checkfix_initrd(VOID *start_addr, memdesc_t *imem)
178 UINTN pgcnt = EFI_SIZE_TO_PAGES(imem->size);
179 UINT64 initrd_addr_max = (UINT64)param_start->s.initrd_addr_max;
180 UINT64 ki_max = initrd_addr_max - imem->size + 1;
183 VERB_PRT( 3, Print(L"loadfile: start_addr="PTR_FMT
184 " ki_max_addr="PTR_FMT"\n", start_addr, (VOID *)ki_max));
185 if (ki_max > UINT32_MAX) {
186 ERR_PRT((L"Force kernel specified initrd_addr_max="PTR_FMT
187 " below 4GB\n", (VOID *)initrd_addr_max));
188 ki_max = UINT32_MAX - imem->size + 1;
190 ki_max_addr = (VOID *)ki_max;
192 if ((UINT64)start_addr > ki_max) {
193 VERB_PRT(1, Print(L"initrd start_addr="PTR_FMT" above "
194 "limit="PTR_FMT"\n", start_addr, ki_max_addr));
198 /* so either the initial allocation failed or it's been to high! */
199 if (start_addr == NULL) {
200 start_addr = alloc_pages(pgcnt, EfiLoaderData,
201 AllocateMaxAddress, ki_max_addr);
203 if ((UINT64)start_addr > ki_max) {
204 ERR_PRT((L"Failed to allocate %d pages below %dMB",
205 pgcnt, (param_start->s.initrd_addr_max+1)>>20));
213 sysdeps_free_boot_params(boot_params_t *bp)
217 ZeroMem(&md, sizeof md);
218 md.md = (VOID *)(UINT64)bp->s.efi_mem_map;
222 static VOID find_bits(unsigned long mask, UINT8 *first, UINT8* len) {
223 unsigned char bit_pos = 0, bit_len = 0;
228 while (!(mask & 0x1)) {
241 * Get video information.
243 static INTN get_video_info(boot_params_t * bp) {
244 EFI_GUID GopProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
245 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop_interface;
246 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Gop_info;
247 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Gop_mode = NULL;
248 EFI_HANDLE *Gop_handle = NULL;
249 EFI_STATUS efi_status;
254 if (x86_64_text_mode() == 1) {
255 Print((L"Skip GOP init, force text-mode.\n"));
258 efi_status = uefi_call_wrapper(
265 (VOID **)Gop_handle);
267 if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) {
268 Print(L"LocateHandle GopProtocol failed.\n");
269 Print(L"--Either no graphics head is installed,\n" \
270 "--efi console is set to serial, or,\n" \
271 "--the EFI firmware version of this machine is\n" \
272 "--older than UEFI 2.0. and does not support GOP");
273 Print(L"you can SAFELY IGNORE this error. elilo will\n" \
274 "default to text-mode.\n Alternatively you can " \
275 "now force text mode by setting config variable\n" \
276 "text_mode=1 for x86 in elilo.conf or via cmdline.\n\n");
277 Print(L"However if this is the last text output you see\n" \
278 "ensure that your kernel console command line\n " \
279 "variable matches up with the actual efi boot menu\n" \
280 "console output settings.\n\n");
283 Gop_handle = alloc(size, 0);
284 efi_status = uefi_call_wrapper(
291 (VOID **)Gop_handle);
292 if (EFI_ERROR(efi_status)) {
293 ERR_PRT((L"LocateHandle GopProtocol failed."));
298 for (i=0; i < size/sizeof(EFI_HANDLE); i++) {
300 efi_status = uefi_call_wrapper(
307 if (EFI_ERROR(efi_status)) {
310 Gop_mode = Gop_interface->Mode;
311 efi_status = uefi_call_wrapper(
312 Gop_interface->QueryMode,
318 if (!EFI_ERROR(efi_status))
320 if (EFI_ERROR(efi_status)) {
324 if (EFI_ERROR(efi_status) || i > (size/sizeof(EFI_HANDLE))) {
325 ERR_PRT((L"HandleProtocol GopProtocol failed."));
331 bp->s.orig_cursor_col = 0;
332 bp->s.orig_cursor_row = 0;
333 bp->s.orig_video_page = 0;
334 bp->s.orig_video_mode = 0;
335 bp->s.orig_video_cols = 0;
336 bp->s.orig_video_rows = 0;
337 bp->s.orig_ega_bx = 0;
338 bp->s.orig_video_points = 0;
340 bp->s.lfb_width = Gop_info->HorizontalResolution;
341 bp->s.lfb_height = Gop_info->VerticalResolution;
342 bp->s.lfb_base = Gop_mode->FrameBufferBase;
343 bp->s.lfb_size = Gop_mode->FrameBufferSize;
347 if (Gop_info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
348 bp->s.lfb_depth = 32;
349 bp->s.lfb_red_size = 8;
350 bp->s.lfb_red_pos = 0;
351 bp->s.lfb_green_size = 8;
352 bp->s.lfb_green_pos = 8;
353 bp->s.lfb_blue_size = 8;
354 bp->s.lfb_blue_pos = 16;
355 bp->s.lfb_rsvd_size = 8;
356 bp->s.lfb_rsvd_pos = 24;
357 bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4;
359 } else if (Gop_info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
360 bp->s.lfb_depth = 32;
361 bp->s.lfb_red_size = 8;
362 bp->s.lfb_red_pos = 16;
363 bp->s.lfb_green_size = 8;
364 bp->s.lfb_green_pos = 8;
365 bp->s.lfb_blue_size = 8;
366 bp->s.lfb_blue_pos = 0;
367 bp->s.lfb_rsvd_size = 8;
368 bp->s.lfb_rsvd_pos = 24;
369 bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4;
370 } else if (Gop_info->PixelFormat == PixelBitMask) {
371 find_bits(Gop_info->PixelInformation.RedMask,
372 &bp->s.lfb_red_pos, &bp->s.lfb_red_size);
373 find_bits(Gop_info->PixelInformation.GreenMask,
374 &bp->s.lfb_green_pos, &bp->s.lfb_green_size);
375 find_bits(Gop_info->PixelInformation.BlueMask,
376 &bp->s.lfb_blue_pos, &bp->s.lfb_blue_size);
377 find_bits(Gop_info->PixelInformation.ReservedMask,
378 &bp->s.lfb_rsvd_pos, &bp->s.lfb_rsvd_size);
379 bp->s.lfb_depth = bp->s.lfb_red_size + bp->s.lfb_green_size +
380 bp->s.lfb_blue_size + bp->s.lfb_rsvd_size;
381 bp->s.lfb_line_len = (Gop_info->PixelsPerScanLine * bp->s.lfb_depth) / 8;
384 bp->s.lfb_red_size = 0;
385 bp->s.lfb_red_pos = 0;
386 bp->s.lfb_green_size = 0;
387 bp->s.lfb_green_pos = 0;
388 bp->s.lfb_blue_size = 0;
389 bp->s.lfb_blue_pos = 0;
390 bp->s.lfb_rsvd_size = 0;
391 bp->s.lfb_rsvd_pos = 0;
392 bp->s.lfb_line_len = bp->s.lfb_width / 2;
398 StrStr(IN const CHAR16 *h, IN const CHAR16 *n)
404 len = StrLen((CHAR16 *)n);
405 while(*t != CHAR_NULL) {
406 res = StrChr( t, n[0]);
407 if (!res) return res;
408 for( i = 1; i < len && res[i] != CHAR_NULL && res[i] == n[i]; i++);
409 if ( i == len ) return res;
411 if (t > h + CMDLINE_MAXLEN) return (CHAR16 *)0;
418 StrStr8(IN const CHAR8 *h, IN const CHAR8 *n)
424 len = strlena((CHAR8 *)n);
426 res = strchra( t, n[0]);
427 if (!res) return res;
428 for( i = 1; i < len && res[i] != 0 && res[i] == n[i]; i++);
429 if ( i == len ) return res;
431 if (t > (h + CMDLINE_MAXLEN)) return (CHAR8 *)0;
437 /* Convert EFI memory map to E820 map for the operating system
438 * This code is based on a Linux kernel patch submitted by Edgar Hucek
441 #if DEBUG_CREATE_BOOT_PARAMS
442 static int e820_max = 6;
444 static int e820_max = E820_MAX;
447 /* Add a memory region to the e820 map */
448 static void add_memory_region (struct e820entry *e820_map,
450 unsigned long long start,
454 int x = *e820_nr_map;
455 static unsigned long long estart = 0ULL;
456 static unsigned long esize = 0L;
457 static unsigned int etype = -1;
458 static int merge = 0;
461 DPR((L"AMR: %3s %4s %16s/%12s/%s\n",
462 L"idx", L" ", L"start", L"size", L"type"));
464 /* merge adjacent regions of same type */
465 if ((x > 0) && e820_map[x-1].addr + e820_map[x-1].size == start
466 && e820_map[x-1].type == type) {
467 e820_map[x-1].size += size;
468 estart = e820_map[x-1].addr;
469 esize = e820_map[x-1].size;
470 etype = e820_map[x-1].type;
474 /* fill up to E820_MAX */
475 if ( x < e820_max ) {
476 e820_map[x].addr = start;
477 e820_map[x].size = size;
478 e820_map[x].type = type;
480 if (merge) DPR((L"AMR: %3d ==> %016llx/%012lx/%d (%d)\n",
481 x-1, estart, esize, etype, merge));
483 DPR((L"AMR: %3d add %016llx/%012lx/%d\n",
484 x, start, size, type));
487 /* different type means another region didn't fit */
488 /* or same type, but there's a hole */
489 if (etype != type || (estart + esize) != start) {
490 if (merge) DPR((L"AMR: %3d ===> %016llx/%012lx/%d (%d)\n",
491 e820_map_overflow, estart, esize, etype, merge));
497 DPR((L"AMR: %3d OVER %016llx/%012lx/%d\n",
498 e820_map_overflow, start, size, type));
501 /* same type and no hole, merge it */
507 void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc)
509 int nr_map, e820_nr_map = 0, i;
510 UINT64 start, end, size;
511 EFI_MEMORY_DESCRIPTOR *md, *p;
512 struct e820entry *e820_map;
514 nr_map = mdesc->map_size/mdesc->desc_size;
515 e820_map = (struct e820entry *)bp->s.e820_map;
517 for (i = 0, p = mdesc->md; i < nr_map; i++)
521 case EfiACPIReclaimMemory:
522 add_memory_region(e820_map, &e820_nr_map,
524 md->NumberOfPages << EFI_PAGE_SHIFT,
527 case EfiRuntimeServicesCode:
528 add_memory_region(e820_map, &e820_nr_map,
530 md->NumberOfPages << EFI_PAGE_SHIFT,
533 case EfiRuntimeServicesData:
534 case EfiReservedMemoryType:
535 case EfiMemoryMappedIO:
536 case EfiMemoryMappedIOPortSpace:
537 case EfiUnusableMemory:
539 add_memory_region(e820_map, &e820_nr_map,
541 md->NumberOfPages << EFI_PAGE_SHIFT,
546 case EfiBootServicesCode:
547 case EfiBootServicesData:
548 case EfiConventionalMemory:
549 start = md->PhysicalStart;
550 size = md->NumberOfPages << EFI_PAGE_SHIFT;
552 /* Fix up for BIOS that claims RAM in 640K-1MB region */
553 if (start < 0x100000ULL && end > 0xA0000ULL) {
554 if (start < 0xA0000ULL) {
556 * set memory map from start to 640K
558 add_memory_region(e820_map,
564 if (end <= 0x100000ULL)
567 * set memory map avoiding 640K to 1MB hole
572 add_memory_region(e820_map, &e820_nr_map,
573 start, size, E820_RAM);
575 case EfiACPIMemoryNVS:
576 add_memory_region(e820_map, &e820_nr_map,
578 md->NumberOfPages << EFI_PAGE_SHIFT,
582 /* We should not hit this case */
583 DBG_PRT((L"hit default!?"));
584 add_memory_region(e820_map, &e820_nr_map,
586 md->NumberOfPages << EFI_PAGE_SHIFT,
590 p = NextMemoryDescriptor(p, mdesc->desc_size);
592 bp->s.e820_nrmap = e820_nr_map;
596 * x86_64 specific boot parameters initialization routine
598 * Note: debug and verbose messages have already been turned off!
601 sysdeps_create_boot_params(
609 EFI_STATUS efi_status;
614 UINT8 e820_map_overflow_warned = 0;
616 #if DEBUG_CREATE_BOOT_PARAMS
621 DBG_PRT((L"fill_boot_params()\n"));
623 if (!bp || !cmdline || !initrd || !cookie) {
624 ERR_PRT((L"bp="PTR_FMT" cmdline="PTR_FMT" initrd="PTR_FMT" cookie="PTR_FMT"",
625 bp, cmdline, initrd, cookie));
627 if (param_start != NULL) {
637 * Copy temporary boot sector and setup data storage to
638 * elilo allocated boot parameter storage. We only need
639 * the first two sectors (1K). The rest of the storage
640 * can be used by the command line.
642 if (param_start != NULL) {
643 CopyMem(bp, param_start, 0x2000);
649 * Save off our header revision information.
651 hdr_version = (bp->s.hdr_major << 8) | bp->s.hdr_minor;
654 * Do NOT clear out unknown memory in boot sector image.
655 * This breaks boot protocol >= 2.10 (2.6.31).
659 * Tell kernel this was loaded by an advanced loader type.
660 * If this field is zero, the initrd_start and initrd_size
661 * fields are ignored by the kernel.
664 bp->s.loader_type = LDRTYPE_ELILO;
667 * Setup command line information.
670 bp->s.cmdline_magik = CMDLINE_MAGIK;
671 bp->s.cmdline_offset = (UINT8 *)cmdline - (UINT8 *)bp;
674 * Clear out the cmdline_addr field so the kernel can find
677 bp->s.cmdline_addr = 0x0;
680 * Setup hard drive parameters.
681 * %%TBD - It should be okay to zero fill the hard drive
682 * info buffers. The kernel should do its own detection.
685 ZeroMem(bp->s.hd0_info, sizeof bp->s.hd0_info);
686 ZeroMem(bp->s.hd1_info, sizeof bp->s.hd1_info);
692 bp->s.alt_mem_k = high_ext_mem / 1024;
694 if (bp->s.alt_mem_k <= 65535)
695 bp->s.ext_mem_k = (UINT16)bp->s.alt_mem_k;
697 bp->s.ext_mem_k = 65535;
700 * Initial RAMdisk and root device stuff.
703 DBG_PRT((L"initrd->start_addr="PTR_FMT" initrd->pgcnt=%d\n",
704 initrd->start_addr, initrd->pgcnt));
706 /* These RAMdisk flags are not needed, just zero them. NOT!*/
707 /* 'ramdisk_flags' (@0x1F8) is called 'ram_size' in the meantime, */
708 /* see Documentation/x86/boot.txt. */
710 if (initrd->start_addr && initrd->pgcnt) {
711 if ( (UINT64)initrd->start_addr > UINT32_MAX ) {
712 ERR_PRT((L"Start of initrd out of reach (>4GB)."));
716 /* %%TBD - This will probably have to be changed. */
717 bp->s.initrd_start = (UINT32)(UINT64)initrd->start_addr;
718 bp->s.initrd_size = (UINT32)(initrd->size);
720 bp->s.initrd_start = 0;
721 bp->s.initrd_size = 0;
727 bp->s.apm_bios_ver = NO_APM_BIOS;
728 bp->s.bios_code_seg = 0;
729 bp->s.bios_entry_point = 0;
730 bp->s.bios_code_seg16 = 0;
731 bp->s.bios_data_seg = 0;
732 bp->s.apm_bios_flags = 0;
733 bp->s.bios_code_len = 0;
734 bp->s.bios_data_len = 0;
737 * MCA BIOS info (misnomer).
739 bp->s.mca_info_len = 0;
740 ZeroMem(bp->s.mca_info_buf, sizeof bp->s.mca_info_buf);
743 * EFI loader signature
745 CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG_X64, 4);
748 * Kernel entry point.
750 if ( (UINT64)kernel_start != (UINT32)(UINT64)kernel_start ) {
751 ERR_PRT((L"Start of kernel (will be) out of reach (>4GB)."));
755 bp->s.kernel_start = (UINT32)(UINT64)kernel_start;
758 * When changing stuff in the parameter structure compare
759 * the offsets of the fields with the offsets used in the
760 * boot sector and setup source files.
761 * arch/x86_64/boot/bootsect.S
762 * arch/x86_64/boot/setup.S
763 * arch/x86_64/kernel/setup.c
764 * include/asm-x86_64/setup.h (2.5/2.6)
767 #define CHECK_OFFSET(n, o, f) \
769 UINTN p = (UINT8 *)&bp->s.n - (UINT8 *)bp; \
770 UINTN q = (UINTN)(o); \
773 Print(L"%20a: %3xh %3xh ", #n, p, q); \
781 #define WAIT_FOR_KEY() \
784 while (uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key) != EFI_SUCCESS) { \
791 CHECK_OFFSET(orig_cursor_col, 0x00, L"%xh");
792 CHECK_OFFSET(orig_cursor_row, 0x01, L"%xh");
793 CHECK_OFFSET(ext_mem_k, 0x02, L"%xh");
794 CHECK_OFFSET(orig_video_page, 0x04, L"%xh");
795 CHECK_OFFSET(orig_video_mode, 0x06, L"%xh");
796 CHECK_OFFSET(orig_video_cols, 0x07, L"%xh");
797 CHECK_OFFSET(orig_ega_bx, 0x0A, L"%xh");
798 CHECK_OFFSET(orig_video_rows, 0x0E, L"%xh");
799 CHECK_OFFSET(is_vga, 0x0F, L"%xh");
800 CHECK_OFFSET(orig_video_points, 0x10, L"%xh");
801 CHECK_OFFSET(lfb_width, 0x12, L"%xh");
802 CHECK_OFFSET(lfb_height, 0x14, L"%xh");
803 CHECK_OFFSET(lfb_depth, 0x16, L"%xh");
804 CHECK_OFFSET(lfb_base, 0x18, L"%xh");
805 CHECK_OFFSET(lfb_size, 0x1C, L"%xh");
806 CHECK_OFFSET(cmdline_magik, 0x20, L"%xh");
807 CHECK_OFFSET(cmdline_offset, 0x22, L"%xh");
808 CHECK_OFFSET(lfb_line_len, 0x24, L"%xh");
809 CHECK_OFFSET(lfb_red_size, 0x26, L"%xh");
810 CHECK_OFFSET(lfb_red_pos, 0x27, L"%xh");
811 CHECK_OFFSET(lfb_green_size, 0x28, L"%xh");
812 CHECK_OFFSET(lfb_green_pos, 0x29, L"%xh");
813 CHECK_OFFSET(lfb_blue_size, 0x2A, L"%xh");
814 CHECK_OFFSET(lfb_blue_pos, 0x2B, L"%xh");
815 CHECK_OFFSET(lfb_rsvd_size, 0x2C, L"%xh");
816 CHECK_OFFSET(lfb_rsvd_pos, 0x2D, L"%xh");
817 CHECK_OFFSET(vesa_seg, 0x2E, L"%xh");
818 CHECK_OFFSET(vesa_off, 0x30, L"%xh");
819 CHECK_OFFSET(lfb_pages, 0x32, L"%xh");
820 CHECK_OFFSET(lfb_reserved, 0x34, L"");
821 CHECK_OFFSET(apm_bios_ver, 0x40, L"%xh");
822 CHECK_OFFSET(bios_code_seg, 0x42, L"%xh");
823 CHECK_OFFSET(bios_entry_point, 0x44, L"%xh");
824 CHECK_OFFSET(bios_code_seg16, 0x48, L"%xh");
825 CHECK_OFFSET(bios_data_seg, 0x4A, L"%xh");
826 CHECK_OFFSET(apm_bios_flags, 0x4C, L"%xh");
827 CHECK_OFFSET(bios_code_len, 0x4E, L"%xh");
828 CHECK_OFFSET(bios_data_len, 0x52, L"%xh");
829 CHECK_OFFSET(hd0_info, 0x80, L"");
830 CHECK_OFFSET(hd1_info, 0x90, L"");
831 CHECK_OFFSET(mca_info_len, 0xA0, L"%xh");
832 CHECK_OFFSET(mca_info_buf, 0xA2, L"");
833 CHECK_OFFSET(efi_loader_sig, 0x1C0, L"'%-4.4a'");
834 CHECK_OFFSET(efi_sys_tbl, 0x1C4, L"%xh");
835 CHECK_OFFSET(efi_mem_desc_size, 0x1C8, L"%xh");
836 CHECK_OFFSET(efi_mem_desc_ver, 0x1CC, L"%xh");
837 CHECK_OFFSET(efi_mem_map, 0x1D0, L"%xh");
838 CHECK_OFFSET(efi_mem_map_size, 0x1D4, L"%xh");
839 CHECK_OFFSET(efi_sys_tbl_hi, 0x1D8, L"%xh");
840 CHECK_OFFSET(efi_mem_map_hi, 0x1DC, L"%xh");
841 CHECK_OFFSET(alt_mem_k, 0x1E0, L"%xh");
842 CHECK_OFFSET(setup_sectors, 0x1F1, L"%xh");
843 CHECK_OFFSET(mount_root_rdonly, 0x1F2, L"%xh");
844 CHECK_OFFSET(sys_size, 0x1F4, L"%xh");
845 CHECK_OFFSET(video_mode_flag, 0x1FA, L"%xh");
846 CHECK_OFFSET(orig_root_dev, 0x1FC, L"%xh");
847 CHECK_OFFSET(boot_flag, 0x1FE, L"%xh");
848 CHECK_OFFSET(jump, 0x200, L"%xh");
849 CHECK_OFFSET(setup_sig, 0x202, L"'%-4.4a'");
850 CHECK_OFFSET(hdr_minor, 0x206, L"%xh");
851 CHECK_OFFSET(hdr_major, 0x207, L"%xh");
852 CHECK_OFFSET(rm_switch, 0x208, L"%xh");
853 CHECK_OFFSET(start_sys_seg, 0x20C, L"%xh");
854 CHECK_OFFSET(kernel_verstr_offset, 0x20E, L"%xh");
855 CHECK_OFFSET(loader_type, 0x210, L"%xh");
856 CHECK_OFFSET(loader_flags, 0x211, L"%xh");
857 CHECK_OFFSET(setup_move_size, 0x212, L"%xh");
858 CHECK_OFFSET(kernel_start, 0x214, L"%xh");
859 CHECK_OFFSET(initrd_start, 0x218, L"%xh");
860 CHECK_OFFSET(initrd_size, 0x21C, L"%xh");
861 CHECK_OFFSET(heap_end_ptr, 0x224, L"%xh");
862 CHECK_OFFSET(cmdline_addr, 0x228, L"%xh");
863 CHECK_OFFSET(e820_map, 0x2D0, L"%xh");
866 ERR_PRT((L"Boot sector and/or setup parameter alignment error."));
873 * Get video information.
874 * Do this last so that any other cursor positioning done
875 * in the fill routine gets accounted for.
878 if (!get_video_info(bp)) goto do_memmap;
880 /* Do the old text mode */
881 efi_status = uefi_call_wrapper(
882 ST->ConOut->QueryMode,
885 ST->ConOut->Mode->Mode,
889 if (EFI_ERROR(efi_status)) {
890 ERR_PRT((L"QueryMode failed. Fake it."));
897 mode = (UINT8)ST->ConOut->Mode->Mode;
898 col = (UINT8)ST->ConOut->Mode->CursorColumn;
899 row = (UINT8)ST->ConOut->Mode->CursorRow;
902 bp->s.orig_cursor_col = col;
903 bp->s.orig_cursor_row = row;
904 bp->s.orig_video_page = 0;
905 bp->s.orig_video_mode = mode;
906 bp->s.orig_video_cols = (UINT8)cols;
907 bp->s.orig_video_rows = (UINT8)rows;
909 bp->s.orig_ega_bx = 0;
911 bp->s.orig_video_points = 16;
914 bp->s.lfb_height = 0;
918 bp->s.lfb_line_len = 0;
919 bp->s.lfb_red_size = 0;
920 bp->s.lfb_red_pos = 0;
921 bp->s.lfb_green_size = 0;
922 bp->s.lfb_green_pos = 0;
923 bp->s.lfb_blue_size = 0;
924 bp->s.lfb_blue_pos = 0;
925 bp->s.lfb_rsvd_size = 0;
926 bp->s.lfb_rsvd_pos = 0;
933 * Get memory map description and cookie for ExitBootServices()
936 if (get_memmap(&mdesc)) {
937 ERR_PRT((L"Could not get memory map."));
941 *cookie = mdesc.cookie;
942 bp->s.efi_mem_map = (UINT32)(unsigned long)mdesc.md;
943 bp->s.efi_mem_map_size = mdesc.map_size;
944 bp->s.efi_mem_desc_size = mdesc.desc_size;
945 bp->s.efi_mem_desc_ver = mdesc.desc_version;
946 bp->s.efi_sys_tbl = (UINT32)(unsigned long)systab;
947 bp->s.efi_mem_map_hi = (unsigned long)mdesc.md >> 32;
948 bp->s.efi_sys_tbl_hi = (unsigned long)systab >> 32;
949 /* Now that we have EFI memory map, convert it to E820 map
950 * and update the bootparam accordingly
952 fill_e820map(bp, &mdesc);
954 #if DEBUG_CREATE_BOOT_PARAMS
955 if ( e820_map_overflow == 0 )
956 e820_map_overflow = -1; /* force second get_memmap()! */
958 if (e820_map_overflow && !e820_map_overflow_warned) {
959 CHAR8 *aem = (CHAR8 *)"add_efi_memmap";
960 e820_map_overflow_warned++;
962 #if DEBUG_CREATE_BOOT_PARAMS
966 if (e820_map_overflow == -1 || StrStr8(cmdline, aem)) {
967 /* Print(L"...mapping again, silently!\n"); */
971 Print(L"\nCAUTION: EFI memory map has %d more entr%a"
972 " than E820 map supports.\n"
973 "To access all memory, '%a' may be necessary.\n\n",
974 e820_map_overflow, (e820_map_overflow==1)?"y":"ies",