2009-05-02 Vladimir Serbinenko <phcoder@gmail.com>
Mmap services * loader/i386/efi/linux.c (grub_linux_boot): use grub_mmap_iterate * loader/i386/linux.c (find_mmap_size): likewise (allocate_pages): likewise * loader/i386/multiboot.c (grub_get_multiboot_mmap_len): likewise (grub_fill_multiboot_mmap): likewise (grub_multiboot): use grub_mmap_get_lower and grub_mmap_get_upper * loader/i386/pc/linux.c (grub_cmd_linux): use grub_mmap_get_lower * include/grub/i386/bsd.h (OPENBSD_MMAP_AVAILABLE): new definition (OPENBSD_MMAP_RESERVED): likewise * include/grub/i386/pc/memory.h: include grub/memory.h (grub_lower_mem): removed (grub_upper_mem): likewise (GRUB_MACHINE_MEMORY_ACPI): new definition (GRUB_MACHINE_MEMORY_NVS): likewise (GRUB_MACHINE_MEMORY_MAX_TYPE): likewise (GRUB_MACHINE_MEMORY_HOLE): likewise (grub_machine_mmap_register): likewise (grub_machine_mmap_unregister): likewise (grub_machine_get_upper): likewise (grub_machine_get_lower): likewise (grub_machine_get_post64): likewise * include/grub/i386/efi/memory.h: new file * include/grub/x86_64/efi/memory.h: likewise * include/grub/efi/memory.h: likewise * conf/i386-pc.rmk (pkglib_MODULES): added mmap.mod (mmap_mod_SOURCES): new variable (mmap_mod_LDFLAGS): likewise (mmap_mod_ASFLAGS): likewise * conf/i386-coreboot.rmk: likewise * conf/i386-ieee1275.rmk: likewise * conf/i386-efi.rmk: likewise * conf/x86_64-efi.rmk: likewise * include/grub/types.h (UINT_TO_PTR): new macro (PTR_TO_UINT32): likewise (PTR_TO_UINT64): likewise * include/grub/memory.h: new file * mmap/i386/pc/mmap.c: likewise * mmap/i386/pc/mmap_helper.S: likewise * mmap/i386/uppermem.c: likewise * mmap/mmap.c: likewise * mmap/efi/mmap.c: likewise * kern/i386/coreboot/init.c (grub_machine_init): don't use grub_upper_mem * kern/i386/pc/init.c (grub_lower_mem): removed variable (grub_upper_mem): likewise (grub_machine_init): don't use grub_upper_mem, make grub_lower_mem local * loader/i386/bsd.c (grub_openbsd_boot): use grub_mmap_get_lower, grub_mmap_iterate and grub_mmap_get_upper (grub_netbsd_boot): use grub_mmap_get_lower and grub_mmap_get_upper
This commit is contained in:
		
							parent
							
								
									d558e6b5ac
								
							
						
					
					
						commit
						09d842b9c6
					
				
					 27 changed files with 1579 additions and 128 deletions
				
			
		
							
								
								
									
										284
									
								
								mmap/efi/mmap.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								mmap/efi/mmap.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,284 @@ | |||
| /* Mmap management. */ | ||||
| /*
 | ||||
|  *  GRUB  --  GRand Unified Bootloader | ||||
|  *  Copyright (C) 2009  Free Software Foundation, Inc. | ||||
|  * | ||||
|  *  GRUB is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  GRUB is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU General Public License | ||||
|  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include <grub/machine/memory.h> | ||||
| #include <grub/memory.h> | ||||
| #include <grub/err.h> | ||||
| #include <grub/efi/api.h> | ||||
| #include <grub/efi/efi.h> | ||||
| #include <grub/mm.h> | ||||
| #include <grub/misc.h> | ||||
| 
 | ||||
| #define NEXT_MEMORY_DESCRIPTOR(desc, size)      \ | ||||
|   ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) | ||||
| 
 | ||||
| grub_err_t | ||||
| grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t,  | ||||
| 							 grub_uint64_t,  | ||||
| 							 grub_uint32_t)) | ||||
| { | ||||
|   grub_efi_uintn_t mmap_size = 0; | ||||
|   grub_efi_memory_descriptor_t *map_buf = 0; | ||||
|   grub_efi_uintn_t map_key = 0; | ||||
|   grub_efi_uintn_t desc_size = 0; | ||||
|   grub_efi_uint32_t desc_version = 0; | ||||
|   grub_efi_memory_descriptor_t *desc; | ||||
| 
 | ||||
|   if (grub_efi_get_memory_map (&mmap_size, map_buf, | ||||
| 			       &map_key, &desc_size, | ||||
| 			       &desc_version) < 0) | ||||
|     return grub_errno; | ||||
| 
 | ||||
|   map_buf = grub_malloc (mmap_size); | ||||
|   if (! map_buf) | ||||
|     return grub_errno; | ||||
| 
 | ||||
|   if (grub_efi_get_memory_map (&mmap_size, map_buf, | ||||
| 			       &map_key, &desc_size, | ||||
| 			       &desc_version) <= 0) | ||||
|     { | ||||
|       grub_free (map_buf); | ||||
|       return grub_errno; | ||||
|     } | ||||
| 
 | ||||
|   for (desc = map_buf; | ||||
|        desc < NEXT_MEMORY_DESCRIPTOR (map_buf, mmap_size); | ||||
|        desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) | ||||
|     { | ||||
|       grub_dprintf ("mmap", "EFI memory region 0x%llx-0x%llx: %d\n", | ||||
| 		    (unsigned long long) desc->physical_start,  | ||||
| 		    (unsigned long long) desc->physical_start | ||||
| 		    + desc->num_pages * 4096, desc->type); | ||||
|       switch (desc->type) | ||||
| 	{ | ||||
| 	case GRUB_EFI_RUNTIME_SERVICES_CODE: | ||||
| 	  hook (desc->physical_start, desc->num_pages * 4096,  | ||||
| 		GRUB_MACHINE_MEMORY_CODE); | ||||
| 	  break; | ||||
| 
 | ||||
| 	default: | ||||
| 	  grub_printf ("Unknown memory type %d, considering reserved\n", | ||||
| 		       desc->type); | ||||
| 
 | ||||
| 	case GRUB_EFI_RESERVED_MEMORY_TYPE: | ||||
| 	case GRUB_EFI_RUNTIME_SERVICES_DATA: | ||||
| 	case GRUB_EFI_UNUSABLE_MEMORY: | ||||
| 	case GRUB_EFI_MEMORY_MAPPED_IO: | ||||
| 	case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: | ||||
| 	case GRUB_EFI_PAL_CODE: | ||||
| 	  hook (desc->physical_start, desc->num_pages * 4096,  | ||||
| 		GRUB_MACHINE_MEMORY_RESERVED); | ||||
| 	  break; | ||||
| 
 | ||||
| 	case GRUB_EFI_LOADER_CODE: | ||||
| 	case GRUB_EFI_LOADER_DATA: | ||||
| 	case GRUB_EFI_BOOT_SERVICES_CODE: | ||||
| 	case GRUB_EFI_BOOT_SERVICES_DATA: | ||||
| 	case GRUB_EFI_CONVENTIONAL_MEMORY: | ||||
| 	  hook (desc->physical_start, desc->num_pages * 4096,  | ||||
| 		GRUB_MACHINE_MEMORY_AVAILABLE); | ||||
| 	  break; | ||||
| 
 | ||||
| 	case GRUB_EFI_ACPI_RECLAIM_MEMORY: | ||||
| 	  hook (desc->physical_start, desc->num_pages * 4096,  | ||||
| 		GRUB_MACHINE_MEMORY_ACPI); | ||||
| 	  break; | ||||
| 
 | ||||
| 	case GRUB_EFI_ACPI_MEMORY_NVS: | ||||
| 	  hook (desc->physical_start, desc->num_pages * 4096,  | ||||
| 		GRUB_MACHINE_MEMORY_NVS); | ||||
| 	  break; | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   return GRUB_ERR_NONE; | ||||
| } | ||||
| 
 | ||||
| static inline grub_efi_memory_type_t  | ||||
| make_efi_memtype (int type) | ||||
| { | ||||
|   switch (type) | ||||
|     { | ||||
|     case GRUB_MACHINE_MEMORY_CODE: | ||||
|       return GRUB_EFI_RUNTIME_SERVICES_CODE; | ||||
| 
 | ||||
|       /* No way to remove a chunk of memory from EFI mmap. 
 | ||||
| 	 So mark it as unusable. */ | ||||
|     case GRUB_MACHINE_MEMORY_HOLE: | ||||
|        | ||||
|     default: | ||||
| 
 | ||||
|     case GRUB_MACHINE_MEMORY_RESERVED: | ||||
|       return GRUB_EFI_UNUSABLE_MEMORY; | ||||
| 
 | ||||
|     case GRUB_MACHINE_MEMORY_AVAILABLE: | ||||
|       return GRUB_EFI_CONVENTIONAL_MEMORY; | ||||
| 
 | ||||
|     case GRUB_MACHINE_MEMORY_ACPI: | ||||
|       return GRUB_EFI_ACPI_RECLAIM_MEMORY; | ||||
| 
 | ||||
|     case GRUB_MACHINE_MEMORY_NVS: | ||||
|       return GRUB_EFI_ACPI_RECLAIM_MEMORY; | ||||
|        | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| struct overlay | ||||
| { | ||||
|   struct overlay *next; | ||||
|   grub_efi_physical_address_t address; | ||||
|   grub_efi_uintn_t pages; | ||||
|   int handle; | ||||
| }; | ||||
| 
 | ||||
| static struct overlay *overlays = 0; | ||||
| static int curhandle = 1; | ||||
| 
 | ||||
| int | ||||
| grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type) | ||||
| { | ||||
|   grub_uint64_t end = start + size; | ||||
|   grub_efi_physical_address_t address; | ||||
|   grub_efi_boot_services_t *b; | ||||
|   grub_efi_uintn_t pages; | ||||
|   grub_efi_status_t status; | ||||
|   struct overlay *curover; | ||||
| 
 | ||||
|   curover = (struct overlay *) grub_malloc (sizeof (struct overlay)); | ||||
|   if (! curover) | ||||
|     return 0; | ||||
|        | ||||
|   b = grub_efi_system_table->boot_services; | ||||
|   address = start & (~0x3ffULL); | ||||
|   pages = (end - address  + 0x3ff) >> 12; | ||||
|   status = efi_call_2 (b->free_pages, address, pages); | ||||
|   if (status != GRUB_EFI_SUCCESS && status != GRUB_EFI_NOT_FOUND) | ||||
|     { | ||||
|       grub_free (curover); | ||||
|       return 0; | ||||
|     } | ||||
|   status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS,  | ||||
| 		       make_efi_memtype (type), pages, &address); | ||||
|   if (status != GRUB_EFI_SUCCESS) | ||||
|     { | ||||
|       grub_free (curover); | ||||
|       return 0; | ||||
|     } | ||||
|   curover->next = overlays; | ||||
|   curover->handle = curhandle++; | ||||
|   curover->address = address; | ||||
|   curover->pages = pages; | ||||
|   overlays = curover; | ||||
| 
 | ||||
|   return curover->handle; | ||||
| } | ||||
| 
 | ||||
| grub_err_t  | ||||
| grub_machine_mmap_unregister (int handle) | ||||
| { | ||||
|   struct overlay *curover, *prevover; | ||||
|   grub_efi_boot_services_t *b; | ||||
|   grub_efi_status_t status; | ||||
| 
 | ||||
|   b = grub_efi_system_table->boot_services; | ||||
| 
 | ||||
|    | ||||
|   for (curover = overlays, prevover = 0; curover;  | ||||
|        prevover = curover, curover = curover->next) | ||||
|     { | ||||
|       if (curover->handle == handle) | ||||
| 	{ | ||||
| 	  status = efi_call_2 (b->free_pages, curover->address, curover->pages); | ||||
| 	  if (prevover != 0) | ||||
| 	    prevover->next = curover->next; | ||||
| 	  else | ||||
| 	    overlays = curover->next; | ||||
| 	  grub_free (curover); | ||||
| 	  return GRUB_ERR_NONE; | ||||
| 	} | ||||
|     } | ||||
|   return grub_error (GRUB_ERR_BAD_ARGUMENT, "handle %d not found", handle); | ||||
| } | ||||
| 
 | ||||
| /* Result is always page-aligned. */ | ||||
| char * | ||||
| grub_mmap_malign_and_register (grub_uint64_t align __attribute__ ((unused)),  | ||||
| 			       grub_uint64_t size, | ||||
| 			       int *handle, int type,  | ||||
| 			       int flags __attribute__ ((unused))) | ||||
| { | ||||
|   grub_efi_physical_address_t address; | ||||
|   grub_efi_boot_services_t *b; | ||||
|   grub_efi_uintn_t pages; | ||||
|   grub_efi_status_t status; | ||||
|   struct overlay *curover; | ||||
|   grub_efi_allocate_type_t atype; | ||||
| 
 | ||||
|   curover = (struct overlay *) grub_malloc (sizeof (struct overlay)); | ||||
|   if (! curover) | ||||
|     return 0; | ||||
|        | ||||
|   b = grub_efi_system_table->boot_services; | ||||
| 
 | ||||
|   address = 0xffffffff; | ||||
| 
 | ||||
| #if GRUB_TARGET_SIZEOF_VOID_P < 8 | ||||
|   /* Limit the memory access to less than 4GB for 32-bit platforms.  */ | ||||
|   atype = GRUB_EFI_ALLOCATE_MAX_ADDRESS; | ||||
| #else | ||||
|   atype = GRUB_EFI_ALLOCATE_ANY_PAGES; | ||||
| #endif | ||||
| 
 | ||||
|   pages = (size + 0x3ff) >> 12; | ||||
|   status = efi_call_4 (b->allocate_pages, atype,  | ||||
| 		       make_efi_memtype (type), pages, &address); | ||||
|   if (status != GRUB_EFI_SUCCESS) | ||||
|     { | ||||
|       grub_free (curover); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
|   if (address == 0) | ||||
|     { | ||||
|       /* Uggh, the address 0 was allocated... This is too annoying,
 | ||||
| 	 so reallocate another one.  */ | ||||
|       address = 0xffffffff; | ||||
|       status = efi_call_4 (b->allocate_pages, atype,  | ||||
| 			   make_efi_memtype (type), pages, &address); | ||||
|       grub_efi_free_pages (0, pages); | ||||
|       if (status != GRUB_EFI_SUCCESS) | ||||
| 	return 0; | ||||
|     } | ||||
|    | ||||
|   curover->next = overlays; | ||||
|   curover->handle = curhandle++; | ||||
|   curover->address = address; | ||||
|   curover->pages = pages; | ||||
|   overlays = curover; | ||||
|   *handle = curover->handle; | ||||
| 
 | ||||
|   return UINT_TO_PTR (curover->address); | ||||
| } | ||||
| 
 | ||||
| void  | ||||
| grub_mmap_free_and_unregister (int handle) | ||||
| { | ||||
|   grub_machine_mmap_unregister (handle); | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue