Welcome to Scribd, the world's digital library. Read, publish, and share books and documents. See more
Standard view
Full view
of .
Save to My Library
Look up keyword
Like this
0 of .
Results for:
No results containing your search query
P. 1
UEFI Memory v E820 Memory

UEFI Memory v E820 Memory

Ratings: (0)|Views: 29 |Likes:
Published by Finnbarr P. Murphy
In this post I discuss the differences between how UEFI hands off memory to the Linux Kernel and how old-fashioned BIOSes handled off memory via E820.

Read more: http://blog.fpmurphy.com/2012/08
In this post I discuss the differences between how UEFI hands off memory to the Linux Kernel and how old-fashioned BIOSes handled off memory via E820.

Read more: http://blog.fpmurphy.com/2012/08

More info:

Published by: Finnbarr P. Murphy on Oct 16, 2012
Copyright:Traditional Copyright: All rights reserved


Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less





UEFI Memory V E820 Memory 
Finnbarr P. Murphy 
 I use theEFI STUBmethod to boot Fedora 17 directly from aUEFIshell without using GRUB. When I got a new Lenovo T430 laptop in July, I found that when I installed a UEFI shell and triedto boot Fedora 17, it simply hung and I had to power cycle the laptop. The problem turned out tobe due to the way memory is reported to the Linux kernel by the laptop firmware.Some background information first before I provide the solution. One of the most vital pieces of information that an operating system (OS) needs in order to initialize itself is a map of availableRAM. The only practical way an OS could get that information up to recently on a PC was via theBIOS.E820is a nickname that refers to the facility by which the BIOS of an x86-based computersystem reports the memory map to an operating system or a boot loader.The nickname comes from the fact that it is accessed via the BIOS INT 15h call, by setting the AXregister to the value OxE820 (Query System Address Map function.) This function has beenavailable on all PCs since 2002 and was available on most PCs for a long time before that. Itreports which memory address ranges (both RAM and ROM) are usable and which are reservedfor use only by the BIOS. E820 memory (see
) is one of the first thingslooked for by a booting Linux kernel (see
.)The idea of using E820 to query platform physical memory was fine while BIOS was thepredominant platform firmware. With the arrival of UEFI firmware, things changed. A UEFI-basedOS typically gets the platform physical memory map using the UEFI
interface.This did not sit easily with many Linux kernel developers. According to Linus Torvalds in an emaildated July 25th, 2006:On Mon, 24 Jul 2006, Andrew Morton wrote:>> > This Patch add an efi e820 memory mapping.> >>> Why?EFI is this other Intel brain-damage (the first one being ACPI). It’s totally differentfrom a normal BIOS, and was brought on by ia64, which never had a BIOS, of course.Sadly, Apple bought into the whole “BIOS bad, EFI good” hype, so we now have x86machines with EFI as the native boot protocol.The original EFI code in the kernel basically duplicates all the BIOS interfaces (ieeverything that looks at a memory map comes in two varieties: the normal and testedBIOS e820 variety, and the usually broken and hacked-up EFI memory map variety).Translating the EFI memory map to e820 is very much the sane thing to do, andshould have been done by ia64 in the first place. Sadly, EFI people (a) think that theirstinking mess is better than a BIOS and (b) are historically ia64-only, so they didn’tdo that, but went the “we’ll just duplicate everything using our inferior EFI interfaces”way.
10-16-2012Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.1/11
UEFI Memory V E820 Memory 
Despite E820 being BIOS-specific, the Linux kernel continues to use the E820 map for thein-kernel representation of the memory address map under EFI as well. This caused (and seems tostill cause) much pain and angst amongst kernel developers. For example, in a proposal in 2010 byBill Richardson to “allow empty e820 map if EFI map will be provided later”, H Peter Anvin’sresponse was:o! Bloody **** hell no!This is yet another attempt at doing more of the wrong thing, which notonly will make it harder to push things that should be earlier in thekernel there.This was settled in 2007 — it is the boot loaders duty to provide amemory map. The fact that we allowed a hack in to let the kernel itself add additional ranges from EFI has proven to be an utter mistake, andthis is yet another example of it. Vetoed in the extreme.-hpaThe solution (hack), arrived at by the Linux kernel developers in 2009 after a number of falsestarts was to add a kernel command line option,
– to tell the kernel to look at theEFI memory map and use it to fix up various entries in the E820 memory map.From
static void __init do_add_efi_memmap(void){void *p;for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {efi_memory_desc_t *md = p;unsigned long long start = md->phys_addr;unsigned long long size = md->num_pages//// Copyright (c) 2012 Finnbarr P. Murphy All rights reserved.//// License: BSD//#include <efi.h>#include <efilib.h>#define PAGE_SIZE 4096const CHAR16 *memory_types[] = {L"EfiReservedMemoryType",L"EfiLoaderCode",L"EfiLoaderData",L"EfiBootServicesCode",L"EfiBootServicesData",L"EfiRuntimeServicesCode",L"EfiRuntimeServicesData",L"EfiConventionalMemory",L"EfiUnusableMemory",L"EfiACPIReclaimMemory",L"EfiACPIMemoryNVS",L"EfiMemoryMappedIO",L"EfiMemoryMappedIOPortSpace",L"EfiPalCode",};
10-16-2012Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.2/11
UEFI Memory V E820 Memory 
const CHAR16 *memory_type_to_str(UINT32 type){if (type > sizeof(memory_types)/sizeof(CHAR16 *))return L"Unknown";return memory_types[type];}EFI_STATUSmemory_map(EFI_MEMORY_DESCRIPTOR **map_buf, UINTN *map_size,UINTN *map_key, UINTN *desc_size, UINT32 *desc_version){EFI_STATUS err = EFI_SUCCESS;*map_size = sizeof(**map_buf) * 31;get_map:*map_size += sizeof(**map_buf);err = uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, *map_size, (void **)map_buf);if (err != EFI_SUCCESS) {Print(L"ERROR: Failed to allocate pool for memory map");return err;}err = uefi_call_wrapper(BS->GetMemoryMap, 5, map_size, *map_buf, map_key, desc_size, desc_version);if (err != EFI_SUCCESS) {if (err == EFI_BUFFER_TOO_SMALL) {uefi_call_wrapper(BS->FreePool, 1, (void *)*map_buf);goto get_map;}Print(L"ERROR: Failed to get memory map");}return err;}EFI_STATUSprint_memory_map(void){EFI_MEMORY_DESCRIPTOR *buf;UINTN desc_size;UINT32 desc_version;UINTN size, map_key, mapping_size;EFI_MEMORY_DESCRIPTOR *desc;EFI_STATUS err = EFI_SUCCESS;int i = 0;err = memory_map(&amp;buf, &amp;size, &amp;map_key, &amp;desc_size, &amp;desc_version);if (err != EFI_SUCCESS)return err;Print(L"Memory Map Size: %d\n", size);Print(L"Map Key: %d\n", map_key);Print(L"Descriptor Version: %d\n", desc_version);Print(L"Descriptor Size: %d\n\n", desc_size);desc = buf;while ((void *)desc < (void *)buf + size) {mapping_size = desc->NumberOfPages * PAGE_SIZE;Print(L"[#%02d] Type: %s Attr: 0x%x\n", i, memory_type_to_str(desc->Type), desc->Attribute);Print(L" Phys: %016llx-%016llx\n", desc->PhysicalStart, desc->PhysicalStart +mapping_size);Print(L" Virt: %016llx-%016llx\n\n", desc->VirtualStart, desc->VirtualStart +mapping_size);desc = (void *)desc + desc_size;i++;}uefi_call_wrapper(BS->FreePool, 1, buf);return err;}EFI_STATUSefi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab){
10-16-2012Copyright 2004-2012 Finnbarr P. Murphy. All rights reserved.3/11

You're Reading a Free Preview

/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->