2N/A/* Memory management for efiemu */ 2N/A * GRUB -- GRand Unified Bootloader 2N/A * Copyright (C) 2009 Free Software Foundation, Inc. 2N/A * GRUB is free software: you can redistribute it and/or modify 2N/A * it under the terms of the GNU General Public License as published by 2N/A * the Free Software Foundation, either version 3 of the License, or 2N/A * (at your option) any later version. 2N/A * GRUB is distributed in the hope that it will be useful, 2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of 2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2N/A * GNU General Public License for more details. 2N/A * You should have received a copy of the GNU General Public License 2N/A To keep efiemu runtime contiguous this mm is special. 2N/A It uses deferred allocation. 2N/A In the first stage you may request memory with grub_efiemu_request_memalign 2N/A It will give you a handle with which in the second phase you can access your 2N/A memory with grub_efiemu_mm_obtain_request (handle). It's guaranteed that 2N/A subsequent calls with the same handle return the same result. You can't request any additional memory once you're in the second phase 2N/A/* Linked list of requested memory. */ 2N/A/* Pointer to allocated memory */ 2N/A/* Size of requested memory per type */ 2N/A/* How many slots is allocated for memory_map and how many are already used */ 2N/A/* Add a memory region to map*/ 2N/A /* Extend map if necessary*/ 2N/A "not enough space for memory map");
2N/A/* Request a resident memory of type TYPE of size SIZE aligned at ALIGN 2N/A ALIGN must be a divisor of page size (if it's a divisor of 4096 2N/A it should be ok on all platforms) 2N/A /* Check that the request is correct */ 2N/A /* Add new size to requested size */ 2N/A /* Remember the request */ 2N/A /* Add request to the end of the chain. 2N/A It should be at the end because otherwise alignment isn't guaranteed */ 2N/A/* Really allocate the memory */ 2N/A /* Order of memory regions */ 2N/A /* First come regions usable by OS*/ 2N/A /* Then memory used by runtime */ 2N/A /* This way all our regions are in a single block */ 2N/A /* And then unavailable memory types. This is more for a completeness. 2N/A You should double think before allocating memory of any of these types 2N/A /* Compute total memory needed */ 2N/A /* Allocate the whole memory in one block */ 2N/A "couldn't allocate resident memory");
2N/A /* Split the memory into blocks by type */ 2N/A /* Write pointers to requests */ 2N/A /* Ensure that the regions are page-aligned */ 2N/A /* Add the region to memory map */ 2N/A/* Get a pointer to requested memory from handle */ 2N/A/* Get type of requested memory by handle */ 2N/A /* Remove head if necessary */ 2N/A /* Remove request from a middle of chain*/ 2N/A/* Reserve space for memory map */ 2N/A // the place for memory used by efiemu itself 2N/A/* This is a drop-in replacement of grub_efi_get_memory_map */ 2N/A/* Get the memory map as defined in the EFI spec. Return 1 if successful, 2N/A return 0 if partial, or return -1 if an error occurs. */ 2N/A "you need to first launch efiemu_prepare");
2N/A/* Free everything */ 2N/A/* This function should be called before doing any requests */ 2N/A/* Copy host memory map */ 2N/A "Unknown memory type %d. Assuming unusable\n",
type);
2N/A/* This function resolves overlapping regions and sorts the memory map 2N/A It uses scanline (sweeping) algorithm 2N/A /* If same page is used by multiple types it's resolved 2N/A according to priority 2N/A 1 - memory immediately usable after ExitBootServices 2N/A 2 - memory usable after loading ACPI tables 2N/A /* Scanline events */ 2N/A /* At which memory address*/ 2N/A /* 0 = region starts, 1 = region ends */ 2N/A /* Which type of memory region */ 2N/A /* Previous scanline event */ 2N/A /* Current scanline event */ 2N/A /* how many regions of given type overlap at current location */ 2N/A /* Here is stored the resulting memory map*/ 2N/A /* Initialize variables*/ 2N/A /* Number of chunks can't increase more than by factor of 2 */ 2N/A "couldn't allocate space for new memory map");
2N/A /* Register scanline events */ 2N/A /* Primitive bubble sort. It has complexity O(n^2) but since we're 2N/A unlikely to have more than 100 chunks it's probably one of the 2N/A fastest for one purpose */ 2N/A /* Pointer in resulting memory map */ 2N/A /* Determine current region type */ 2N/A /* Add memory region to resulting map if necessary */ 2N/A /* We set runtime attribute on pages we need to be mapped */ 2N/A "mmap entry: type %d start 0x%llx 0x%llx pages\n",
2N/A /* Update last values if necessary */ 2N/A /* Shrink resulting memory map to really used size and replace efiemu_mmap 2N/A/* This function is called to switch from first to second phase */ 2N/A /* Preallocate mmap */