Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/stand/efiboot Add initrd support.
details: https://anonhg.NetBSD.org/src/rev/2a11fc271261
branches: trunk
changeset: 433319:2a11fc271261
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Fri Sep 07 17:30:58 2018 +0000
description:
Add initrd support.
diffstat:
sys/stand/efiboot/boot.c | 28 +++++++++++++-
sys/stand/efiboot/efiboot.h | 4 +-
sys/stand/efiboot/efifdt.c | 42 ++++++++++++++++++++-
sys/stand/efiboot/efifdt.h | 5 ++-
sys/stand/efiboot/exec.c | 88 +++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 159 insertions(+), 8 deletions(-)
diffs (290 lines):
diff -r 25021cc541cc -r 2a11fc271261 sys/stand/efiboot/boot.c
--- a/sys/stand/efiboot/boot.c Fri Sep 07 17:30:32 2018 +0000
+++ b/sys/stand/efiboot/boot.c Fri Sep 07 17:30:58 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: boot.c,v 1.5 2018/09/03 00:17:00 jmcneill Exp $ */
+/* $NetBSD: boot.c,v 1.6 2018/09/07 17:30:58 jmcneill Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -53,17 +53,20 @@
#define DEFTIMEOUT 5
static char default_device[32];
+static char initrd_path[255];
void command_boot(char *);
void command_dev(char *);
+void command_initrd(char *);
void command_ls(char *);
void command_reset(char *);
void command_version(char *);
void command_quit(char *);
const struct boot_command commands[] = {
- { "boot", command_boot, "boot [fsN:][filename] [args]\n (ex. \"fs0:\\netbsd.old -s\"" },
+ { "boot", command_boot, "boot [dev:][filename] [args]\n (ex. \"hd0a:\\netbsd.old -s\"" },
{ "dev", command_dev, "dev" },
+ { "initrd", command_initrd, "initrd [dev:][filename]" },
{ "ls", command_ls, "ls [hdNn:/path]" },
{ "version", command_version, "version" },
{ "help", command_help, "help|?" },
@@ -111,6 +114,12 @@
}
void
+command_initrd(char *arg)
+{
+ set_initrd_path(arg);
+}
+
+void
command_ls(char *arg)
{
ls(arg);
@@ -157,6 +166,21 @@
return default_device;
}
+int
+set_initrd_path(char *arg)
+{
+ if (strlen(arg) + 1 > sizeof(initrd_path))
+ return ERANGE;
+ strcpy(initrd_path, arg);
+ return 0;
+}
+
+char *
+get_initrd_path(void)
+{
+ return initrd_path;
+}
+
void
print_banner(void)
{
diff -r 25021cc541cc -r 2a11fc271261 sys/stand/efiboot/efiboot.h
--- a/sys/stand/efiboot/efiboot.h Fri Sep 07 17:30:32 2018 +0000
+++ b/sys/stand/efiboot/efiboot.h Fri Sep 07 17:30:58 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efiboot.h,v 1.3 2018/09/03 00:04:02 jmcneill Exp $ */
+/* $NetBSD: efiboot.h,v 1.4 2018/09/07 17:30:58 jmcneill Exp $ */
/*-
* Copyright (c) 2016 Kimihiro Nonaka <nonaka%netbsd.org@localhost>
@@ -52,6 +52,8 @@
void command_help(char *);
int set_default_device(char *);
char *get_default_device(void);
+int set_initrd_path(char *);
+char *get_initrd_path(void);
/* console.c */
int ischar(void);
diff -r 25021cc541cc -r 2a11fc271261 sys/stand/efiboot/efifdt.c
--- a/sys/stand/efiboot/efifdt.c Fri Sep 07 17:30:32 2018 +0000
+++ b/sys/stand/efiboot/efifdt.c Fri Sep 07 17:30:58 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efifdt.c,v 1.7 2018/09/03 00:17:00 jmcneill Exp $ */
+/* $NetBSD: efifdt.c,v 1.8 2018/09/07 17:30:58 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -78,6 +78,28 @@
}
void
+efi_fdt_init(u_long addr, u_long len)
+{
+ int error;
+
+ error = fdt_open_into(fdt_data, (void *)addr, len);
+ if (error < 0)
+ panic("fdt_open_into failed: %d", error);
+
+ fdt_data = (void *)addr;
+}
+
+void
+efi_fdt_fini(void)
+{
+ int error;
+
+ error = fdt_pack(fdt_data);
+ if (error < 0)
+ panic("fdt_pack failed: %d", error);
+}
+
+void
efi_fdt_show(void)
{
const char *model, *compat;
@@ -194,3 +216,21 @@
}
}
}
+
+void
+efi_fdt_initrd(u_long initrd_addr, u_long initrd_size)
+{
+ int chosen;
+
+ if (initrd_size == 0)
+ return;
+
+ chosen = fdt_path_offset(fdt_data, FDT_CHOSEN_NODE_PATH);
+ if (chosen < 0)
+ chosen = fdt_add_subnode(fdt_data, fdt_path_offset(fdt_data, "/"), FDT_CHOSEN_NODE_NAME);
+ if (chosen < 0)
+ panic("FDT: Failed to create " FDT_CHOSEN_NODE_PATH " node");
+
+ fdt_setprop_u64(fdt_data, chosen, "linux,initrd-start", initrd_addr);
+ fdt_setprop_u64(fdt_data, chosen, "linux,initrd-end", initrd_addr + initrd_size);
+}
diff -r 25021cc541cc -r 2a11fc271261 sys/stand/efiboot/efifdt.h
--- a/sys/stand/efiboot/efifdt.h Fri Sep 07 17:30:32 2018 +0000
+++ b/sys/stand/efiboot/efifdt.h Fri Sep 07 17:30:58 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efifdt.h,v 1.2 2018/09/03 00:17:00 jmcneill Exp $ */
+/* $NetBSD: efifdt.h,v 1.3 2018/09/07 17:30:58 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -32,3 +32,6 @@
int efi_fdt_size(void);
void efi_fdt_show(void);
void efi_fdt_bootargs(const char *);
+void efi_fdt_initrd(u_long, u_long);
+void efi_fdt_init(u_long, u_long);
+void efi_fdt_fini(void);
diff -r 25021cc541cc -r 2a11fc271261 sys/stand/efiboot/exec.c
--- a/sys/stand/efiboot/exec.c Fri Sep 07 17:30:32 2018 +0000
+++ b/sys/stand/efiboot/exec.c Fri Sep 07 17:30:58 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: exec.c,v 1.3 2018/09/02 23:50:23 jmcneill Exp $ */
+/* $NetBSD: exec.c,v 1.4 2018/09/07 17:30:58 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -33,6 +33,78 @@
u_long load_offset = 0;
+#define FDT_SPACE (4 * 1024 * 1024)
+#define FDT_ALIGN ((2 * 1024 * 1024) - 1)
+
+static EFI_PHYSICAL_ADDRESS initrd_addr;
+static u_long initrd_size = 0;
+
+static int
+load_initrd(void)
+{
+ EFI_STATUS status;
+ struct stat st;
+ ssize_t len;
+ char *path;
+ int fd;
+
+ path = get_initrd_path();
+ if (strlen(path) == 0)
+ return 0;
+
+ fd = open(path, 0);
+ if (fd < 0) {
+ printf("boot: failed to open %s: %s\n", path, strerror(errno));
+ return errno;
+ }
+ if (fstat(fd, &st) < 0) {
+ printf("boot: failed to fstat %s: %s\n", path, strerror(errno));
+ close(fd);
+ return errno;
+ }
+ if (st.st_size == 0) {
+ printf("boot: empty initrd %s\n", path);
+ close(fd);
+ return EINVAL;
+ }
+
+ initrd_size = st.st_size;
+
+#ifdef EFIBOOT_ALLOCATE_MAX_ADDRESS
+ initrd_addr = EFIBOOT_ALLOCATE_MAX_ADDRESS;
+ status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData,
+ EFI_SIZE_TO_PAGES(initrd_size), &initrd_addr);
+#else
+ initrd_addr = 0;
+ status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiLoaderData,
+ EFI_SIZE_TO_PAGES(initrd_size), &initrd_addr);
+#endif
+ if (EFI_ERROR(status)) {
+ printf("Failed to allocate %lu bytes for initrd image (error %lu)\n",
+ initrd_size, status);
+ close(fd);
+ return ENOMEM;
+ }
+
+ printf("boot: loading %s ", path);
+ len = read(fd, (void *)initrd_addr, initrd_size);
+ close(fd);
+
+ if (len != initrd_size) {
+ if (len < 0)
+ printf(": %s\n", strerror(errno));
+ else
+ printf(": returned %ld (expected %ld)\n", len, initrd_size);
+ return EIO;
+ }
+
+ printf("done.\n");
+
+ efi_dcache_flush(initrd_addr, initrd_size);
+
+ return 0;
+}
+
int
exec_netbsd(const char *fname, const char *args)
{
@@ -41,6 +113,8 @@
EFI_STATUS status;
int fd;
+ load_initrd();
+
memset(marks, 0, sizeof(marks));
fd = loadfile(fname, marks, COUNT_KERNEL | LOAD_NOTE);
if (fd < 0) {
@@ -49,7 +123,7 @@
}
close(fd);
marks[MARK_END] = (((u_long) marks[MARK_END] + sizeof(int) - 1)) & (-sizeof(int));
- alloc_size = marks[MARK_END] - marks[MARK_START] + EFIBOOT_ALIGN;
+ alloc_size = marks[MARK_END] - marks[MARK_START] + FDT_SPACE + EFIBOOT_ALIGN;
#ifdef EFIBOOT_ALLOCATE_MAX_ADDRESS
addr = EFIBOOT_ALLOCATE_MAX_ADDRESS;
@@ -77,8 +151,11 @@
load_offset = 0;
if (efi_fdt_size() > 0) {
+ efi_fdt_init((marks[MARK_END] + FDT_ALIGN) & ~FDT_ALIGN, FDT_ALIGN + 1);
+ efi_fdt_initrd(initrd_addr, initrd_size);
efi_fdt_bootargs(args);
- efi_fdt_memory_map();
+ efi_fdt_memory_map();
+ efi_fdt_fini();
}
efi_cleanup();
@@ -89,5 +166,10 @@
cleanup:
uefi_call_wrapper(BS->FreePages, 2, addr, EFI_SIZE_TO_PAGES(alloc_size));
+ if (initrd_addr) {
+ uefi_call_wrapper(BS->FreePages, 2, initrd_addr, EFI_SIZE_TO_PAGES(initrd_size));
+ initrd_addr = 0;
+ initrd_size = 0;
+ }
return EIO;
}
Home |
Main Index |
Thread Index |
Old Index