Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157922409
D49863.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D49863.id.diff
View Options
diff --git a/stand/kboot/include/efi.h b/stand/kboot/include/efi.h
--- a/stand/kboot/include/efi.h
+++ b/stand/kboot/include/efi.h
@@ -13,6 +13,15 @@
typedef void (*efi_map_entry_cb)(struct efi_md *, void *argp);
+struct preloaded_file;
+
+bool efi_read_from_pa(uint64_t pa, uint32_t map_size, uint32_t desc_size, uint32_t vers);
+void efi_read_from_sysfs(void);
+void efi_set_systbl(uint64_t tbl);
void foreach_efi_map_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, void *argp);
void print_efi_map(struct efi_map_header *efihdr);
-bool populate_avail_from_efi(struct efi_map_header *efihdr);
+void efi_bi_loadsmap(struct preloaded_file *kfp);
+
+extern uint32_t efi_map_size;
+extern vm_paddr_t efi_map_phys_src; /* From DTB */
+extern vm_paddr_t efi_map_phys_dst; /* From our memory map metadata module */
diff --git a/stand/kboot/kboot/arch/aarch64/exec.c b/stand/kboot/kboot/arch/aarch64/exec.c
--- a/stand/kboot/kboot/arch/aarch64/exec.c
+++ b/stand/kboot/kboot/arch/aarch64/exec.c
@@ -41,6 +41,7 @@
#include <machine/metadata.h>
#include "bootstrap.h"
+#include "efi.h"
#include "kboot.h"
#include "platform/acfreebsd.h"
@@ -65,11 +66,7 @@
bool do_mem_map = false;
-extern uint32_t efi_map_size;
-extern vm_paddr_t efi_map_phys_src; /* From DTB */
-extern vm_paddr_t efi_map_phys_dst; /* From our memory map metadata module */
-
-/* Usually provided by loader_efi.h */
+/* Usually provided by loader_efi.h -- maybe just delete? */
#ifndef EFI
int bi_load(char *args, vm_offset_t *modulep, vm_offset_t *kernendp,
bool exit_bs);
diff --git a/stand/kboot/kboot/arch/aarch64/load_addr.c b/stand/kboot/kboot/arch/aarch64/load_addr.c
--- a/stand/kboot/kboot/arch/aarch64/load_addr.c
+++ b/stand/kboot/kboot/arch/aarch64/load_addr.c
@@ -11,30 +11,18 @@
#include <libfdt.h>
#include "kboot.h"
-#include "bootstrap.h"
#include "efi.h"
-/*
- * Info from dtb about the EFI system
- */
-vm_paddr_t efi_systbl_phys;
-struct efi_map_header *efi_map_hdr;
-uint32_t efi_map_size;
-vm_paddr_t efi_map_phys_src; /* From DTB */
-vm_paddr_t efi_map_phys_dst; /* From our memory map metadata module */
-
static bool
do_memory_from_fdt(int fd)
{
struct stat sb;
char *buf = NULL;
- int len, offset, fd2 = -1;
- uint32_t sz, ver, esz, efisz;
+ int len, offset;
+ uint32_t sz, ver, esz;
uint64_t mmap_pa;
const uint32_t *u32p;
const uint64_t *u64p;
- struct efi_map_header *efihdr;
- struct efi_md *map;
if (fstat(fd, &sb) < 0)
return false;
@@ -60,7 +48,7 @@
u64p = fdt_getprop(buf, offset, "linux,uefi-system-table", &len);
if (u64p == NULL)
goto errout;
- efi_systbl_phys = fdt64_to_cpu(*u64p);
+ efi_set_systbl(fdt64_to_cpu(*u64p));
u32p = fdt_getprop(buf, offset, "linux,uefi-mmap-desc-ver", &len);
if (u32p == NULL)
goto errout;
@@ -82,62 +70,8 @@
printf("UEFI MMAP: Ver %d Ent Size %d Tot Size %d PA %#lx\n",
ver, esz, sz, mmap_pa);
- /*
- * We may have no ability to read the PA that this map is in, so pass
- * the address to FreeBSD via a rather odd flag entry as the first map
- * so early boot can copy the memory map into this space and have the
- * rest of the code cope.
- */
- efisz = roundup2(sizeof(*efihdr), 16);
- buf = malloc(sz + efisz);
- if (buf == NULL)
- return false;
- efihdr = (struct efi_map_header *)buf;
- map = (struct efi_md *)((uint8_t *)efihdr + efisz);
- bzero(map, sz);
- efihdr->memory_size = sz;
- efihdr->descriptor_size = esz;
- efihdr->descriptor_version = ver;
-
- /*
- * Save EFI table. Either this will be an empty table filled in by the trampoline,
- * or we'll read it below. Either way, set these two variables so we share the best
- * UEFI memory map with the kernel.
- */
- efi_map_hdr = efihdr;
- efi_map_size = sz + efisz;
-
- /*
- * Try to read in the actual UEFI map.
- */
- fd2 = open("host:/dev/mem", O_RDONLY);
- if (fd2 < 0) {
- printf("Will read UEFI mem map in tramp: no /dev/mem, need CONFIG_DEVMEM=y\n");
- goto no_read;
- }
- if (lseek(fd2, mmap_pa, SEEK_SET) < 0) {
- printf("Will read UEFI mem map in tramp: lseek failed\n");
- goto no_read;
- }
- len = read(fd2, map, sz);
- if (len != sz) {
- if (len < 0 && errno == EPERM)
- printf("Will read UEFI mem map in tramp: kernel needs CONFIG_STRICT_DEVMEM=n\n");
- else
- printf("Will read UEFI mem map in tramp: lean = %d errno = %d\n", len, errno);
- goto no_read;
- }
- printf("Read UEFI mem map from physmem\n");
- efi_map_phys_src = 0; /* Mark MODINFOMD_EFI_MAP as valid */
- close(fd2);
- printf("UEFI MAP:\n");
- print_efi_map(efihdr);
- return true; /* OK, we really have the memory map */
-
-no_read:
- efi_map_phys_src = mmap_pa;
- close(fd2);
- return true; /* We can get it the trampoline */
+ efi_read_from_pa(mmap_pa, sz, esz, ver);
+ return true;
errout:
free(buf);
@@ -150,22 +84,32 @@
int fd = -1;
bool rv = false;
+ /*
+ * FDT publishes the parameters for the memory table in a series of
+ * nodes in the DTB. One of them is the physical address for the memory
+ * table. Try to open the fdt nblob to find this information if we can
+ * and try to grab things from memory. If we return rv == TRUE then
+ * we found it. The global efi_map_phys_src is set != 0 when we know
+ * the PA but can't read it.
+ */
fd = open("host:/sys/firmware/fdt", O_RDONLY);
if (fd != -1) {
rv = do_memory_from_fdt(fd);
close(fd);
- /*
- * So, we have physaddr to the memory table. However, we can't
- * open /dev/mem on some platforms to get the actual table. So
- * we have to fall through to get it from /proc/iomem.
- */
}
+
+ /*
+ * One would think that one could use the raw EFI map to find memory
+ * that's free to boot the kernel with. However, Linux reserves some
+ * areas that it needs to properly. I'm not sure if the printf should be
+ * a panic, but for now, so I can debug (maybe at the loader prompt),
+ * I'm printing and carrying on.
+ */
if (!rv) {
printf("Could not obtain UEFI memory tables, expect failure\n");
}
populate_avail_from_iomem();
-
print_avail();
return true;
@@ -181,32 +125,19 @@
if (s != 0)
return (s);
+ print_avail();
s = first_avail(KERN_ALIGN, HOLE_SIZE, SYSTEM_RAM);
+ printf("KBOOT GET PHYS Using %#llx\n", (long long)s);
if (s != 0)
return (s);
s = 0x40000000 | 0x4200000; /* should never get here */
- printf("Falling back to crazy address %#lx\n", s);
+ /* XXX PANIC? XXX */
+ printf("Falling back to the crazy address %#lx which works in qemu\n", s);
return (s);
}
void
bi_loadsmap(struct preloaded_file *kfp)
{
-
- /*
- * Make a note of a systbl. This is nearly mandatory on AARCH64.
- */
- if (efi_systbl_phys)
- file_addmetadata(kfp, MODINFOMD_FW_HANDLE, sizeof(efi_systbl_phys), &efi_systbl_phys);
-
- /*
- * If we have efi_map_hdr, then it's a pointer to the PA where this
- * memory map lives. The trampoline code will copy it over. If we don't
- * have it, we use whatever we found in /proc/iomap.
- */
- if (efi_map_hdr != NULL) {
- file_addmetadata(kfp, MODINFOMD_EFI_MAP, efi_map_size, efi_map_hdr);
- return;
- }
- panic("Can't get UEFI memory map, nor a pointer to it, can't proceed.\n");
+ efi_bi_loadsmap(kfp);
}
diff --git a/stand/kboot/libkboot/Makefile b/stand/kboot/libkboot/Makefile
--- a/stand/kboot/libkboot/Makefile
+++ b/stand/kboot/libkboot/Makefile
@@ -5,6 +5,7 @@
.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}
CFLAGS+=-I${.CURDIR} -I${.CURDIR}/arch/${MACHINE_ARCH}
+CFLAGS+=-I${LDRSRC}
SRCS= crt1.c
SRCS+= host_syscall.S
diff --git a/stand/kboot/libkboot/efi.c b/stand/kboot/libkboot/efi.c
--- a/stand/kboot/libkboot/efi.c
+++ b/stand/kboot/libkboot/efi.c
@@ -5,9 +5,156 @@
*/
#include <sys/param.h>
+#include <sys/linker.h>
#include "stand.h"
+#include "bootstrap.h"
#include "efi.h"
#include "seg.h"
+#include "util.h"
+
+vm_paddr_t efi_systbl_phys;
+struct efi_map_header *efi_map_hdr;
+uint32_t efi_map_size;
+vm_paddr_t efi_map_phys_src; /* From DTB */
+vm_paddr_t efi_map_phys_dst; /* From our memory map metadata module */
+
+void
+efi_set_systbl(uint64_t tbl)
+{
+ efi_systbl_phys = tbl;
+}
+
+#if 0
+/* Note: This is useless since runtime-map is a subset */
+void
+efi_read_from_sysfs(void)
+{
+ uint32_t efisz, sz, map_size;
+ int entries = 0;
+ struct efi_md *map; /* Really an array */
+ char *buf;
+ struct stat sb;
+ char fn[100];
+
+ /*
+ * Count the number of entries we have. They are numbered from 0
+ * through entries - 1.
+ */
+ do {
+ printf("Looking at index %d\n", entries);
+ snprintf(fn, sizeof(fn), "/sys/firmware/efi/runtime-map/%d/phys_addr", entries++);
+ } while (stat(fn, &sb) == 0);
+
+ /*
+ * We incremented entries one past the first failure, so we need to
+ * adjust the count and the test for 'nothing found' is against 1.
+ */
+ if (entries == 1)
+ goto err;
+ entries--;
+
+ /* XXX lots of copied code, refactor? */
+ map_size = sizeof(struct efi_md) * entries;
+ efisz = roundup2(sizeof(*efi_map_hdr), 16);
+ sz = efisz + map_size;
+ buf = malloc(efisz + map_size);
+ if (buf == NULL)
+ return;
+ efi_map_hdr = (struct efi_map_header *)buf;
+ efi_map_size = sz;
+ map = (struct efi_md *)(buf + efisz);
+ bzero(map, sz);
+ efi_map_hdr->memory_size = map_size;
+ efi_map_hdr->descriptor_size = sizeof(struct efi_md);
+ efi_map_hdr->descriptor_version = EFI_MEMORY_DESCRIPTOR_VERSION;
+ for (int i = 0; i < entries; i++) {
+ struct efi_md *m;
+
+ printf("Populating index %d\n", i);
+ m = map + i;
+ snprintf(fn, sizeof(fn), "/sys/firmware/efi/runtime-map/%d/type", i);
+ if (!file2u32(fn, &m->md_type))
+ goto err;
+ snprintf(fn, sizeof(fn), "/sys/firmware/efi/runtime-map/%d/phys_addr", i);
+ if (!file2u64(fn, &m->md_phys))
+ goto err;
+ snprintf(fn, sizeof(fn), "/sys/firmware/efi/runtime-map/%d/virt_addr", i);
+ if (!file2u64(fn, &m->md_virt))
+ goto err;
+ snprintf(fn, sizeof(fn), "/sys/firmware/efi/runtime-map/%d/num_pages", i);
+ if (!file2u64(fn, &m->md_pages))
+ goto err;
+ snprintf(fn, sizeof(fn), "/sys/firmware/efi/runtime-map/%d/attribute", i);
+ if (!file2u64(fn, &m->md_attr))
+ goto err;
+ }
+ efi_map_phys_src = 0;
+ printf("UEFI MAP:\n");
+ print_efi_map(efi_map_hdr);
+ printf("DONE\n");
+ return;
+err:
+ printf("Parse error in reading current memory map\n");
+}
+#endif
+
+/*
+ * We may have no ability to read the PA that this map is in, so pass
+ * the address to FreeBSD via a rather odd flag entry as the first map
+ * so early boot can copy the memory map into this space and have the
+ * rest of the code cope.
+ */
+bool
+efi_read_from_pa(uint64_t pa, uint32_t map_size, uint32_t desc_size, uint32_t vers)
+{
+ uint32_t efisz, sz;
+ char *buf;
+ int fd2, len;
+ struct efi_md *map; /* Really an array */
+
+ /*
+ * We may have no ability to read the PA that this map is in, so pass
+ * the address to FreeBSD via a rather odd flag entry as the first map
+ * so early boot can copy the memory map into this space and have the
+ * rest of the code cope. We also have to round the size of the header
+ * to 16 byte boundary.
+ */
+ efisz = roundup2(sizeof(*efi_map_hdr), 16);
+ sz = efisz + map_size;
+ buf = malloc(efisz + map_size);
+ if (buf == NULL)
+ return false;
+ efi_map_hdr = (struct efi_map_header *)buf;
+ efi_map_size = sz;
+ map = (struct efi_md *)(buf + efisz);
+ bzero(map, sz);
+ efi_map_hdr->memory_size = map_size;
+ efi_map_hdr->descriptor_size = desc_size;
+ efi_map_hdr->descriptor_version = vers;
+
+ /*
+ * Try to read in the actual UEFI map. This may fail, and that's OK. We just
+ * won't print the map.
+ */
+ fd2 = open("host:/dev/mem", O_RDONLY);
+ if (fd2 < 0)
+ goto no_read;
+ if (lseek(fd2, pa, SEEK_SET) < 0)
+ goto no_read;
+ len = read(fd2, map, sz);
+ if (len != sz)
+ goto no_read;
+ efi_map_phys_src = 0; /* Mark MODINFOMD_EFI_MAP as valid */
+ close(fd2);
+ printf("UEFI MAP:\n");
+ print_efi_map(efi_map_hdr);
+ return (true);
+
+no_read: /* Just get it the trampoline */
+ efi_map_phys_src = pa;
+ close(fd2);
+ return (true);
+}
void
foreach_efi_map_entry(struct efi_map_header *efihdr, efi_map_entry_cb cb, void *argp)
@@ -98,37 +245,25 @@
foreach_efi_map_entry(efihdr, print_efi_map_entry, NULL);
}
-static void
-efi_map_entry_add_avail(struct efi_md *p, void *argp)
+void
+efi_bi_loadsmap(struct preloaded_file *kfp)
{
- bool *retval = argp;
-
/*
- * The kernel itself uses a lot more types as memory it can use. Be
- * conservative here so we don't overwrite anything during the reboot
- * process which copies the new kernel (so we can't use the Linux kenrel
- * space for example). Anything that's not free, we simply don't add to
- * the system ram space. We just need to find a big enough place we can
- * land the kernel, and most of the other types we might use are
- * typically too small anyway, even if we could safely use them.
+ * Make a note of a systbl. This is nearly mandatory on AARCH64.
*/
- if (p->md_type != EFI_MD_TYPE_FREE)
- return;
+ if (efi_systbl_phys)
+ file_addmetadata(kfp, MODINFOMD_FW_HANDLE, sizeof(efi_systbl_phys), &efi_systbl_phys);
/*
- * The memory map is always disjoint, so we never have to remove avail.
+ * If we have efi_map_hdr, then it's a pointer to the PA where this
+ * memory map lives. The trampoline code will copy it over. If we don't
+ * have it, panic because /proc/iomem isn't sufficient and there's no
+ * hope.
*/
- add_avail(p->md_phys, p->md_phys + p->md_pages * EFI_PAGE_SIZE - 1,
- SYSTEM_RAM);
- *retval = true;
-}
-
-bool
-populate_avail_from_efi(struct efi_map_header *efihdr)
-{
- bool retval = false;
+ if (efi_map_hdr != NULL) {
+ file_addmetadata(kfp, MODINFOMD_EFI_MAP, efi_map_size, efi_map_hdr);
+ return;
+ }
- init_avail();
- foreach_efi_map_entry(efihdr, efi_map_entry_add_avail, &retval);
- return retval;
+ panic("Can't get UEFI memory map, nor a pointer to it, can't proceed.\n");
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, May 27, 12:50 PM (8 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33551466
Default Alt Text
D49863.id.diff (13 KB)
Attached To
Mode
D49863: kboot: Move common EFI stuff from aarch64 to libkboot
Attached
Detach File
Event Timeline
Log In to Comment