Module Name:    src
Committed By:   jmcneill
Date:           Fri Aug 24 23:20:41 UTC 2018

Modified Files:
        src/sys/stand/efiboot: efifdt.c

Log Message:
Sanitize the memory map passed to the kernel.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/stand/efiboot/efifdt.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/stand/efiboot/efifdt.c
diff -u src/sys/stand/efiboot/efifdt.c:1.1 src/sys/stand/efiboot/efifdt.c:1.2
--- src/sys/stand/efiboot/efifdt.c:1.1	Fri Aug 24 02:01:06 2018
+++ src/sys/stand/efiboot/efifdt.c	Fri Aug 24 23:20:41 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: efifdt.c,v 1.1 2018/08/24 02:01:06 jmcneill Exp $ */
+/* $NetBSD: efifdt.c,v 1.2 2018/08/24 23:20:41 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca>
@@ -79,8 +79,9 @@ void
 efi_fdt_memory_map(void)
 {
 	UINTN nentries = 0, mapkey, descsize;
-	EFI_MEMORY_DESCRIPTOR *md;
+	EFI_MEMORY_DESCRIPTOR *md, *memmap;
 	UINT32 descver;
+	UINT64 phys_start, phys_size;
 	int n, memory;
 
 	memory = fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH);
@@ -90,30 +91,49 @@ efi_fdt_memory_map(void)
 		panic("FDT: Failed to create " FDT_MEMORY_NODE_PATH " node");
 
 	fdt_delprop(fdt_data, memory, "reg");
+	while (fdt_num_mem_rsv(fdt_data) > 0) {
+		if (fdt_del_mem_rsv(fdt_data, 0) < 0)
+			panic("FDT: Failed to remove reserved memory map entry");
+	}
 
 	const int address_cells = fdt_address_cells(fdt_data, fdt_path_offset(fdt_data, "/"));
 	const int size_cells = fdt_size_cells(fdt_data, fdt_path_offset(fdt_data, "/"));
 
-	md = LibMemoryMap(&nentries, &mapkey, &descsize, &descver);
-	for (n = 0; n < nentries; n++, md = NextMemoryDescriptor(md, descsize)) {
+	memmap = LibMemoryMap(&nentries, &mapkey, &descsize, &descver);
+	for (n = 0, md = memmap; n < nentries; n++, md = NextMemoryDescriptor(md, descsize)) {
 		if ((md->Attribute & EFI_MEMORY_WB) == 0)
 			continue;
 		if (!FDT_MEMORY_USABLE(md))
 			continue;
+		if ((address_cells == 1 || size_cells == 1) && md->PhysicalStart + (md->NumberOfPages * EFI_PAGE_SIZE) > 0xffffffff)
+			continue;
+		if (md->NumberOfPages <= 1)
+			continue;
+
+		phys_start = md->PhysicalStart;
+		phys_size = md->NumberOfPages * EFI_PAGE_SIZE;
+
+		if (phys_start & EFI_PAGE_MASK) {
+			/* UEFI spec says these should be 4KB aligned, but U-Boot doesn't always.. */
+			phys_start = (phys_start + EFI_PAGE_SIZE) & ~EFI_PAGE_MASK;
+			phys_size -= (EFI_PAGE_SIZE * 2);
+			if (phys_size == 0)
+				continue;
+		}
 
 		if (address_cells == 1)
 			fdt_appendprop_u32(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
-			    "reg", (uint32_t)md->PhysicalStart);
+			    "reg", (uint32_t)phys_start);
 		else
 			fdt_appendprop_u64(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
-			    "reg", md->PhysicalStart);
+			    "reg", phys_start);
 
 		if (size_cells == 1)
 			fdt_appendprop_u32(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
-			    "reg", (uint32_t)md->NumberOfPages * EFI_PAGE_SIZE);
+			    "reg", (uint32_t)phys_size);
 		else
 			fdt_appendprop_u64(fdt_data, fdt_path_offset(fdt_data, FDT_MEMORY_NODE_PATH),
-			    "reg", (uint64_t)md->NumberOfPages * EFI_PAGE_SIZE);
+			    "reg", phys_size);
 	}
 }
 

Reply via email to