summaryrefslogtreecommitdiffstats
path: root/sys/boot/ia64/common
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2002-10-24 07:53:12 +0000
committermarcel <marcel@FreeBSD.org>2002-10-24 07:53:12 +0000
commitf7ce7ae0befa71e36c461d0e6a6846f32035729d (patch)
treeb8e25a327c8f7b40236fd40d06db6a7d14caf6fa /sys/boot/ia64/common
parent98d67f5e31ff245c7f97399e38ecccee170adee3 (diff)
downloadFreeBSD-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/ia64/common')
-rw-r--r--sys/boot/ia64/common/bootinfo.c27
-rw-r--r--sys/boot/ia64/common/exec.c24
2 files changed, 35 insertions, 16 deletions
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);
OpenPOWER on IntegriCloud