diff options
author | marcel <marcel@FreeBSD.org> | 2002-10-24 07:53:12 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2002-10-24 07:53:12 +0000 |
commit | f7ce7ae0befa71e36c461d0e6a6846f32035729d (patch) | |
tree | b8e25a327c8f7b40236fd40d06db6a7d14caf6fa /sys/boot | |
parent | 98d67f5e31ff245c7f97399e38ecccee170adee3 (diff) | |
download | FreeBSD-src-f7ce7ae0befa71e36c461d0e6a6846f32035729d.zip FreeBSD-src-f7ce7ae0befa71e36c461d0e6a6846f32035729d.tar.gz |
o Fix a size calculation based on a 8KB page, while under EFI
pages are 4KB.
o As a second order fix, don't assume we have enough space
after the bootinfo block left in a page to hold the memory
map.
o A third order fix as that we removed the assumption that a
bootinfo block fits in a single 8KB page.
PR: ia64/39415
submitted by: Espen Skoglund <esk@ira.uka.de>
Diffstat (limited to 'sys/boot')
-rw-r--r-- | sys/boot/efi/libefi/bootinfo.c | 27 | ||||
-rw-r--r-- | sys/boot/efi/libefi/efiboot.h | 2 | ||||
-rw-r--r-- | sys/boot/efi/libefi/elf_freebsd.c | 24 | ||||
-rw-r--r-- | sys/boot/ia64/common/bootinfo.c | 27 | ||||
-rw-r--r-- | sys/boot/ia64/common/exec.c | 24 |
5 files changed, 71 insertions, 33 deletions
diff --git a/sys/boot/efi/libefi/bootinfo.c b/sys/boot/efi/libefi/bootinfo.c index 1d3e956..484f226 100644 --- a/sys/boot/efi/libefi/bootinfo.c +++ b/sys/boot/efi/libefi/bootinfo.c @@ -244,7 +244,8 @@ bi_copymodules(vm_offset_t addr) * - Module metadata are formatted and placed in kernel space. */ int -bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) +bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey, + UINTN pages) { char *rootdevname; struct efi_devdesc *rootdev; @@ -254,7 +255,7 @@ bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) vm_offset_t ssym, esym; struct file_metadata *md; EFI_STATUS status; - UINTN key; + UINTN bisz, key; /* * Version 1 bootinfo. @@ -273,9 +274,9 @@ bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) bi->bi_systab = (u_int64_t) ST; /* - * Allow the environment variable 'rootdev' to override the supplied device - * This should perhaps go to MI code and/or have $rootdev tested/set by - * MI code before launching the kernel. + * Allow the environment variable 'rootdev' to override the supplied + * device. This should perhaps go to MI code and/or have $rootdev + * tested/set by MI code before launching the kernel. */ rootdevname = getenv("rootdev"); efi_getdev((void **)(&rootdev), rootdevname, NULL); @@ -331,14 +332,16 @@ bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) /* all done copying stuff in, save end of loaded object space */ bi->bi_kernend = addr; - /* read memory map and stash it after bootinfo */ - bi->bi_memmap = (u_int64_t)(bi + 1); - bi->bi_memmap_size = 8192 - sizeof(struct bootinfo); + /* + * Read the memory map and stash it after bootinfo. Align the memory map + * on a 16-byte boundary (the bootinfo block is page aligned). + */ + bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; + bi->bi_memmap = ((u_int64_t)bi) + bisz; + bi->bi_memmap_size = EFI_PAGE_SIZE * pages - bisz; status = BS->GetMemoryMap(&bi->bi_memmap_size, - (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, - &key, - &bi->bi_memdesc_size, - &bi->bi_memdesc_version); + (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, &key, + &bi->bi_memdesc_size, &bi->bi_memdesc_version); if (EFI_ERROR(status)) { printf("bi_load: Can't read memory map\n"); return EINVAL; diff --git a/sys/boot/efi/libefi/efiboot.h b/sys/boot/efi/libefi/efiboot.h index 780554e..3b680d6 100644 --- a/sys/boot/efi/libefi/efiboot.h +++ b/sys/boot/efi/libefi/efiboot.h @@ -88,4 +88,4 @@ extern int fpswa_init(u_int64_t *fpswa_interface); struct bootinfo; struct preloaded_file; extern int bi_load(struct bootinfo *, struct preloaded_file *, - UINTN *mapkey); + UINTN *mapkey, UINTN pages); diff --git a/sys/boot/efi/libefi/elf_freebsd.c b/sys/boot/efi/libefi/elf_freebsd.c index 5c95d0f..91736cc 100644 --- a/sys/boot/efi/libefi/elf_freebsd.c +++ b/sys/boot/efi/libefi/elf_freebsd.c @@ -143,15 +143,31 @@ elf_exec(struct preloaded_file *fp) struct ia64_pte pte; struct bootinfo *bi; u_int64_t psr; - UINTN mapkey; + UINTN mapkey, pages, size; + UINTN descsz; + UINT32 descver; EFI_STATUS status; if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); /* XXX actually EFUCKUP */ hdr = (Elf_Ehdr *)&(md->md_data); - status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, - EFI_SIZE_TO_PAGES(sizeof(struct bootinfo)), (void*)&bi); + /* + * Allocate enough pages to hold the bootinfo block and the memory + * map EFI will return to us. The memory map has an unknown size, + * so we have to determine that first. Note that the AllocatePages + * call can itself modify the memory map, so we have to take that + * into account as well. The changes to the memory map are caused + * by splitting a range of free memory into two (AFAICT), so that + * one is marked as being loader data. + */ + size = 0; + descsz = sizeof(EFI_MEMORY_DESCRIPTOR); + BS->GetMemoryMap(&size, NULL, &mapkey, &descsz, &descver); + size += descsz + ((sizeof(struct bootinfo) + 0x0f) & ~0x0f); + pages = EFI_SIZE_TO_PAGES(size); + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, + (void*)&bi); if (EFI_ERROR(status)) { printf("unable to create bootinfo block (status=0x%lx)\n", (long)status); @@ -159,7 +175,7 @@ elf_exec(struct preloaded_file *fp) } bzero(bi, sizeof(struct bootinfo)); - bi_load(bi, fp, &mapkey); + bi_load(bi, fp, &mapkey, pages); printf("Entering %s at 0x%lx...\n", fp->f_name, hdr->e_entry); diff --git a/sys/boot/ia64/common/bootinfo.c b/sys/boot/ia64/common/bootinfo.c index 1d3e956..484f226 100644 --- a/sys/boot/ia64/common/bootinfo.c +++ b/sys/boot/ia64/common/bootinfo.c @@ -244,7 +244,8 @@ bi_copymodules(vm_offset_t addr) * - Module metadata are formatted and placed in kernel space. */ int -bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) +bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey, + UINTN pages) { char *rootdevname; struct efi_devdesc *rootdev; @@ -254,7 +255,7 @@ bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) vm_offset_t ssym, esym; struct file_metadata *md; EFI_STATUS status; - UINTN key; + UINTN bisz, key; /* * Version 1 bootinfo. @@ -273,9 +274,9 @@ bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) bi->bi_systab = (u_int64_t) ST; /* - * Allow the environment variable 'rootdev' to override the supplied device - * This should perhaps go to MI code and/or have $rootdev tested/set by - * MI code before launching the kernel. + * Allow the environment variable 'rootdev' to override the supplied + * device. This should perhaps go to MI code and/or have $rootdev + * tested/set by MI code before launching the kernel. */ rootdevname = getenv("rootdev"); efi_getdev((void **)(&rootdev), rootdevname, NULL); @@ -331,14 +332,16 @@ bi_load(struct bootinfo *bi, struct preloaded_file *fp, UINTN *mapkey) /* all done copying stuff in, save end of loaded object space */ bi->bi_kernend = addr; - /* read memory map and stash it after bootinfo */ - bi->bi_memmap = (u_int64_t)(bi + 1); - bi->bi_memmap_size = 8192 - sizeof(struct bootinfo); + /* + * Read the memory map and stash it after bootinfo. Align the memory map + * on a 16-byte boundary (the bootinfo block is page aligned). + */ + bisz = (sizeof(struct bootinfo) + 0x0f) & ~0x0f; + bi->bi_memmap = ((u_int64_t)bi) + bisz; + bi->bi_memmap_size = EFI_PAGE_SIZE * pages - bisz; status = BS->GetMemoryMap(&bi->bi_memmap_size, - (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, - &key, - &bi->bi_memdesc_size, - &bi->bi_memdesc_version); + (EFI_MEMORY_DESCRIPTOR *)bi->bi_memmap, &key, + &bi->bi_memdesc_size, &bi->bi_memdesc_version); if (EFI_ERROR(status)) { printf("bi_load: Can't read memory map\n"); return EINVAL; diff --git a/sys/boot/ia64/common/exec.c b/sys/boot/ia64/common/exec.c index 5c95d0f..91736cc 100644 --- a/sys/boot/ia64/common/exec.c +++ b/sys/boot/ia64/common/exec.c @@ -143,15 +143,31 @@ elf_exec(struct preloaded_file *fp) struct ia64_pte pte; struct bootinfo *bi; u_int64_t psr; - UINTN mapkey; + UINTN mapkey, pages, size; + UINTN descsz; + UINT32 descver; EFI_STATUS status; if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return(EFTYPE); /* XXX actually EFUCKUP */ hdr = (Elf_Ehdr *)&(md->md_data); - status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, - EFI_SIZE_TO_PAGES(sizeof(struct bootinfo)), (void*)&bi); + /* + * Allocate enough pages to hold the bootinfo block and the memory + * map EFI will return to us. The memory map has an unknown size, + * so we have to determine that first. Note that the AllocatePages + * call can itself modify the memory map, so we have to take that + * into account as well. The changes to the memory map are caused + * by splitting a range of free memory into two (AFAICT), so that + * one is marked as being loader data. + */ + size = 0; + descsz = sizeof(EFI_MEMORY_DESCRIPTOR); + BS->GetMemoryMap(&size, NULL, &mapkey, &descsz, &descver); + size += descsz + ((sizeof(struct bootinfo) + 0x0f) & ~0x0f); + pages = EFI_SIZE_TO_PAGES(size); + status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, + (void*)&bi); if (EFI_ERROR(status)) { printf("unable to create bootinfo block (status=0x%lx)\n", (long)status); @@ -159,7 +175,7 @@ elf_exec(struct preloaded_file *fp) } bzero(bi, sizeof(struct bootinfo)); - bi_load(bi, fp, &mapkey); + bi_load(bi, fp, &mapkey, pages); printf("Entering %s at 0x%lx...\n", fp->f_name, hdr->e_entry); |