X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=ia32%2Fsystem.c;h=078d40650a2aca096be6704653f0549a65b7e544;hb=3384f0373c8758e5ddd08f489ad7110898dd5406;hp=1dbbc587d6ae5e844f15435c68c91232f4e1fd41;hpb=8e0034665aa8483b27191c723608575536d01303;p=debian%2Felilo diff --git a/ia32/system.c b/ia32/system.c index 1dbbc58..078d406 100644 --- a/ia32/system.c +++ b/ia32/system.c @@ -97,7 +97,10 @@ UINTN high_base_mem = 0x90000; UINTN high_ext_mem = 32 * 1024 * 1024; /* This starting address will hold true for all of the loader types for now */ -VOID *kernel_start = (VOID *)0x100000; /* 1M */ +VOID *kernel_start = (VOID *)DEFAULT_KERNEL_START; + +/* The kernel may load elsewhere if EFI firmware reserves kernel_start */ +VOID *kernel_load_address = (VOID *)DEFAULT_KERNEL_START; VOID *initrd_start = NULL; UINTN initrd_size = 0; @@ -131,16 +134,16 @@ sysdeps_initrd_get_addr(kdesc_t *kd, memdesc_t *imem) DBG_PRT((L"initrd_get_addr()\n")); if (!kd || !imem) { - ERR_PRT((L"kd=0x%x imem=0x%x", kd, imem)); + ERR_PRT((L"kd=" PTR_FMT " imem=" PTR_FMT, kd, imem)); return -1; } - VERB_PRT(3, Print(L"kstart=0x%x kentry=0x%x kend=0x%x\n", + VERB_PRT(3, Print(L"kstart=" PTR_FMT " kentry=" PTR_FMT " kend=" PTR_FMT "\n", kd->kstart, kd->kentry, kd->kend)); imem->start_addr = kd->kend; - VERB_PRT(3, Print(L"initrd start_addr=0x%x pgcnt=%d\n", + VERB_PRT(3, Print(L"initrd start_addr=" PTR_FMT " pgcnt=%d\n", imem->start_addr, imem->pgcnt)); return 0; @@ -156,6 +159,276 @@ sysdeps_free_boot_params(boot_params_t *bp) free_memmap(&md); } +static VOID find_bits(unsigned long mask, UINT8 *first, UINT8* len) { + unsigned char bit_pos = 0, bit_len = 0; + *first =0; + *len = 0; + if (mask == 0) + return; + while (!(mask & 0x1)) { + mask = mask >> 1; + bit_pos++; + } + while (mask & 0x1) { + mask = mask >> 1; + bit_len++; + } + *first = bit_pos; + *len = bit_len; +} + +/* + * Get video information. + */ +static INTN get_video_info(boot_params_t * bp) { + EFI_GUID GopProtocol = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop_interface; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Gop_info; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Gop_mode = NULL; + EFI_HANDLE *Gop_handle = NULL; + EFI_STATUS efi_status; + UINTN size = 0; + UINTN size1; + UINT8 i; + + efi_status = uefi_call_wrapper( + BS->LocateHandle, + 5, + ByProtocol, + &GopProtocol, + NULL, + &size, + (VOID **)Gop_handle); + + if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) { + ERR_PRT((L"LocateHandle GopProtocol failed.")); + return -1; + } + Gop_handle = alloc(size, 0); + efi_status = uefi_call_wrapper( + BS->LocateHandle, + 5, + ByProtocol, + &GopProtocol, + NULL, + &size, + (VOID **)Gop_handle); + if (EFI_ERROR(efi_status)) { + ERR_PRT((L"LocateHandle GopProtocol failed.")); + free(Gop_handle); + return -1; + } + + for (i=0; i < size/sizeof(EFI_HANDLE); i++) { + Gop_handle += i; + efi_status = uefi_call_wrapper( + BS->HandleProtocol, + 3, + *Gop_handle, + &GopProtocol, + (VOID **) &Gop_interface); + + if (EFI_ERROR(efi_status)) { + continue; + } + Gop_mode = Gop_interface->Mode; + efi_status = uefi_call_wrapper( + Gop_interface->QueryMode, + 4, + Gop_interface, + Gop_mode->Mode, + &size1, + &Gop_info); + if (!EFI_ERROR(efi_status)) + break; + if (EFI_ERROR(efi_status)) { + continue; + } + } + if (EFI_ERROR(efi_status) || i > (size/sizeof(EFI_HANDLE))) { + ERR_PRT((L"HandleProtocol GopProtocol failed.")); + free(Gop_handle); + return -1; + } + + bp->s.is_vga = 0x70; + bp->s.orig_cursor_col = 0; + bp->s.orig_cursor_row = 0; + bp->s.orig_video_page = 0; + bp->s.orig_video_mode = 0; + bp->s.orig_video_cols = 0; + bp->s.orig_video_rows = 0; + bp->s.orig_ega_bx = 0; + bp->s.orig_video_points = 0; + + bp->s.lfb_width = Gop_info->HorizontalResolution; + bp->s.lfb_height = Gop_info->VerticalResolution; + bp->s.lfb_base = Gop_mode->FrameBufferBase; + bp->s.lfb_size = Gop_mode->FrameBufferSize; + bp->s.lfb_pages = 1; + bp->s.vesa_seg = 0; + bp->s.vesa_off = 0; + if (Gop_info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor) { + bp->s.lfb_depth = 32; + bp->s.lfb_red_size = 8; + bp->s.lfb_red_pos = 0; + bp->s.lfb_green_size = 8; + bp->s.lfb_green_pos = 8; + bp->s.lfb_blue_size = 8; + bp->s.lfb_blue_pos = 16; + bp->s.lfb_rsvd_size = 8; + bp->s.lfb_rsvd_pos = 24; + bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4; + + } else if (Gop_info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor) { + bp->s.lfb_depth = 32; + bp->s.lfb_red_size = 8; + bp->s.lfb_red_pos = 16; + bp->s.lfb_green_size = 8; + bp->s.lfb_green_pos = 8; + bp->s.lfb_blue_size = 8; + bp->s.lfb_blue_pos = 0; + bp->s.lfb_rsvd_size = 8; + bp->s.lfb_rsvd_pos = 24; + bp->s.lfb_line_len = Gop_info->PixelsPerScanLine * 4; + } else if (Gop_info->PixelFormat == PixelBitMask) { + find_bits(Gop_info->PixelInformation.RedMask, + &bp->s.lfb_red_pos, &bp->s.lfb_red_size); + find_bits(Gop_info->PixelInformation.GreenMask, + &bp->s.lfb_green_pos, &bp->s.lfb_green_size); + find_bits(Gop_info->PixelInformation.BlueMask, + &bp->s.lfb_blue_pos, &bp->s.lfb_blue_size); + find_bits(Gop_info->PixelInformation.ReservedMask, + &bp->s.lfb_rsvd_pos, &bp->s.lfb_rsvd_size); + bp->s.lfb_depth = bp->s.lfb_red_size + bp->s.lfb_green_size + + bp->s.lfb_blue_size + bp->s.lfb_rsvd_size; + bp->s.lfb_line_len = (Gop_info->PixelsPerScanLine * bp->s.lfb_depth) / 8; + } else { + bp->s.lfb_depth = 4; + bp->s.lfb_red_size = 0; + bp->s.lfb_red_pos = 0; + bp->s.lfb_green_size = 0; + bp->s.lfb_green_pos = 0; + bp->s.lfb_blue_size = 0; + bp->s.lfb_blue_pos = 0; + bp->s.lfb_rsvd_size = 0; + bp->s.lfb_rsvd_pos = 0; + bp->s.lfb_line_len = bp->s.lfb_width / 2; + } + return 0; +} + +/* Convert EFI memory map to E820 map for the operating system + * This code is based on a Linux kernel patch submitted by Edgar Hucek + */ + +/* Add a memory region to the e820 map */ +static void add_memory_region (struct e820entry *e820_map, + int *e820_nr_map, + UINT64 start, + UINT64 size, + UINT32 type) +{ + int x = *e820_nr_map; + + if (x == E820_MAX) { + Print(L"Too many entries in the memory map!\n"); + return; + } + + if ((x > 0) && e820_map[x-1].addr + e820_map[x-1].size == start + && e820_map[x-1].type == type) + e820_map[x-1].size += size; + else { + e820_map[x].addr = start; + e820_map[x].size = size; + e820_map[x].type = type; + (*e820_nr_map)++; + } +} + +void fill_e820map(boot_params_t *bp, mmap_desc_t *mdesc) +{ + int nr_map, e820_nr_map = 0, i; + UINT64 start, end, size; + EFI_MEMORY_DESCRIPTOR *md, *p; + struct e820entry *e820_map; + + nr_map = mdesc->map_size/mdesc->desc_size; + e820_map = (struct e820entry *)bp->s.e820_map; + + for (i = 0, p = mdesc->md; i < nr_map; i++) + { + md = p; + switch (md->Type) { + case EfiACPIReclaimMemory: + add_memory_region(e820_map, &e820_nr_map, + md->PhysicalStart, + md->NumberOfPages << EFI_PAGE_SHIFT, + E820_ACPI); + break; + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiReservedMemoryType: + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: + case EfiUnusableMemory: + case EfiPalCode: + add_memory_region(e820_map, &e820_nr_map, + md->PhysicalStart, + md->NumberOfPages << EFI_PAGE_SHIFT, + E820_RESERVED); + break; + case EfiLoaderCode: + case EfiLoaderData: + case EfiBootServicesCode: + case EfiBootServicesData: + case EfiConventionalMemory: + start = md->PhysicalStart; + size = md->NumberOfPages << EFI_PAGE_SHIFT; + end = start + size; + /* Fix up for BIOS that claims RAM in 640K-1MB region */ + if (start < 0x100000ULL && end > 0xA0000ULL) { + if (start < 0xA0000ULL) { + /* start < 640K + * set memory map from start to 640K + */ + add_memory_region(e820_map, + &e820_nr_map, + start, + 0xA0000ULL-start, + E820_RAM); + } + if (end <= 0x100000ULL) + continue; + /* end > 1MB + * set memory map avoiding 640K to 1MB hole + */ + start = 0x100000ULL; + size = end - start; + } + add_memory_region(e820_map, &e820_nr_map, + start, size, E820_RAM); + break; + case EfiACPIMemoryNVS: + add_memory_region(e820_map, &e820_nr_map, + md->PhysicalStart, + md->NumberOfPages << EFI_PAGE_SHIFT, + E820_NVS); + break; + default: + /* We should not hit this case */ + add_memory_region(e820_map, &e820_nr_map, + md->PhysicalStart, + md->NumberOfPages << EFI_PAGE_SHIFT, + E820_RESERVED); + break; + } + p = NextMemoryDescriptor(p, mdesc->desc_size); + } + bp->s.e820_nrmap = e820_nr_map; +} + /* * IA-32 specific boot parameters initialization routine */ @@ -177,7 +450,7 @@ sysdeps_create_boot_params( DBG_PRT((L"fill_boot_params()\n")); if (!bp || !cmdline || !initrd || !cookie) { - ERR_PRT((L"bp=0x%x cmdline=0x%x initrd=0x%x cookie=0x%x", + ERR_PRT((L"bp=" PTR_FMT " cmdline=" PTR_FMT " initrd=" PTR_FMT " cookie=" PTR_FMT, bp, cmdline, initrd, cookie)); if (param_start != NULL) { @@ -213,9 +486,11 @@ sysdeps_create_boot_params( bp->s.unused_2 = 0; ZeroMem(bp->s.unused_3, sizeof bp->s.unused_3); ZeroMem(bp->s.unused_4, sizeof bp->s.unused_4); - ZeroMem(bp->s.unused_5, sizeof bp->s.unused_5); + ZeroMem(&bp->s.unused_51, sizeof bp->s.unused_51); + ZeroMem(bp->s.unused_52, sizeof bp->s.unused_52); bp->s.unused_6 = 0; bp->s.unused_7 = 0; + ZeroMem(bp->s.unused_8, sizeof bp->s.unused_8); /* * Tell kernel this was loaded by an advanced loader type. @@ -262,7 +537,7 @@ sysdeps_create_boot_params( * Initial RAMdisk and root device stuff. */ - DBG_PRT((L"initrd->start_addr=0x%x initrd->pgcnt=%d\n", + DBG_PRT((L"initrd->start_addr=" PTR_FMT " initrd->pgcnt=%d\n", initrd->start_addr, initrd->pgcnt)); /* These RAMdisk flags are not needed, just zero them. */ @@ -310,7 +585,7 @@ sysdeps_create_boot_params( /* * EFI loader signature */ - CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG, 4); + CopyMem(bp->s.efi_loader_sig, EFI_LOADER_SIG_IA32, 4); /* * Kernel entry point. @@ -344,7 +619,7 @@ sysdeps_create_boot_params( #define WAIT_FOR_KEY() \ { \ EFI_INPUT_KEY key; \ - while (ST->ConIn->ReadKeyStroke(ST->ConIn, &key) != EFI_SUCCESS) { \ + while (uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key) != EFI_SUCCESS) { \ ; \ } \ } @@ -402,6 +677,7 @@ sysdeps_create_boot_params( CHECK_OFFSET(loader_start, 0x1D8, L"%xh"); CHECK_OFFSET(loader_size, 0x1DC, L"%xh"); CHECK_OFFSET(alt_mem_k, 0x1E0, L"%xh"); + CHECK_OFFSET(e820_nrmap, 0x1E8, L"%xh"); CHECK_OFFSET(setup_sectors, 0x1F1, L"%xh"); CHECK_OFFSET(mount_root_rdonly, 0x1F2, L"%xh"); CHECK_OFFSET(sys_size, 0x1F4, L"%xh"); @@ -426,6 +702,7 @@ sysdeps_create_boot_params( CHECK_OFFSET(bootsect_helper, 0x220, L"%xh"); CHECK_OFFSET(heap_end_ptr, 0x224, L"%xh"); CHECK_OFFSET(cmdline_addr, 0x228, L"%xh"); + CHECK_OFFSET(e820_map, 0x2D0, L"'%-2560.2560a'"); if (test) { ERR_PRT((L"Boot sector and/or setup parameter alignment error.")); @@ -440,7 +717,11 @@ sysdeps_create_boot_params( * in the fill routine gets accounted for. */ - efi_status = ST->ConOut->QueryMode( + if (!get_video_info(bp)) goto do_memmap; + + efi_status = uefi_call_wrapper( + ST->ConOut->QueryMode, + 4, ST->ConOut, ST->ConOut->Mode->Mode, &cols, @@ -488,6 +769,7 @@ sysdeps_create_boot_params( bp->s.vesa_seg = 0; bp->s.vesa_off = 0; +do_memmap: /* * Get memory map description and cookie for ExitBootServices() */ @@ -503,6 +785,10 @@ sysdeps_create_boot_params( bp->s.efi_mem_desc_size = mdesc.desc_size; bp->s.efi_mem_desc_ver = mdesc.desc_version; bp->s.efi_sys_tbl = (UINTN)systab; + /* Now that we have EFI memory map, convert it to E820 map + * and update the bootparam accordingly + */ + fill_e820map(bp, &mdesc); return 0; }