8139 loader: efi multiboot2 update
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
diff --git a/usr/src/boot/sys/boot/efi/loader/main.c b/usr/src/boot/sys/boot/efi/loader/main.c
index 269f7df..472ce86 100644
--- a/usr/src/boot/sys/boot/efi/loader/main.c
+++ b/usr/src/boot/sys/boot/efi/loader/main.c
@@ -65,6 +65,7 @@
extern void acpi_detect(void);
void efi_serial_init(void);
+extern void efi_getsmap(void);
#ifdef EFI_ZFS_BOOT
static void efi_zfs_probe(void);
#endif
@@ -209,6 +210,8 @@
archsw.arch_copyin = efi_copyin;
archsw.arch_copyout = efi_copyout;
archsw.arch_readin = efi_readin;
+ archsw.arch_loadaddr = efi_loadaddr;
+ archsw.arch_free_loadaddr = efi_free_loadaddr;
#ifdef EFI_ZFS_BOOT
/* Note this needs to be set before ZFS init. */
archsw.arch_zfs_probe = efi_zfs_probe;
@@ -226,6 +229,7 @@
* printf() etc. once this is done.
*/
cons_probe();
+ efi_getsmap();
/*
* Initialise the block cache. Set the upper limit.
@@ -329,11 +333,6 @@
setenv("console", "ttya" , 1);
}
- if (efi_copy_init()) {
- printf("failed to allocate staging area\n");
- return (EFI_BUFFER_TOO_SMALL);
- }
-
/*
* March through the device switch probing for things.
*/
@@ -796,6 +795,104 @@
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
#endif
+/*
+ * Chain load another efi loader.
+ */
+static int
+command_chain(int argc, char *argv[])
+{
+ EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
+ EFI_HANDLE loaderhandle;
+ EFI_LOADED_IMAGE *loaded_image;
+ EFI_STATUS status;
+ struct stat st;
+ struct devdesc *dev;
+ char *name, *path;
+ void *buf;
+ int fd;
+
+ if (argc < 2) {
+ command_errmsg = "wrong number of arguments";
+ return (CMD_ERROR);
+ }
+
+ name = argv[1];
+
+ if ((fd = open(name, O_RDONLY)) < 0) {
+ command_errmsg = "no such file";
+ return (CMD_ERROR);
+ }
+
+ if (fstat(fd, &st) < -1) {
+ command_errmsg = "stat failed";
+ close(fd);
+ return (CMD_ERROR);
+ }
+
+ status = BS->AllocatePool(EfiLoaderCode, (UINTN)st.st_size, &buf);
+ if (status != EFI_SUCCESS) {
+ command_errmsg = "failed to allocate buffer";
+ close(fd);
+ return (CMD_ERROR);
+ }
+ if (read(fd, buf, st.st_size) != st.st_size) {
+ command_errmsg = "error while reading the file";
+ (void)BS->FreePool(buf);
+ close(fd);
+ return (CMD_ERROR);
+ }
+ close(fd);
+ status = BS->LoadImage(FALSE, IH, NULL, buf, st.st_size, &loaderhandle);
+ (void)BS->FreePool(buf);
+ if (status != EFI_SUCCESS) {
+ command_errmsg = "LoadImage failed";
+ return (CMD_ERROR);
+ }
+ status = BS->HandleProtocol(loaderhandle, &LoadedImageGUID,
+ (void **)&loaded_image);
+
+ if (argc > 2) {
+ int i, len = 0;
+ CHAR16 *argp;
+
+ for (i = 2; i < argc; i++)
+ len += strlen(argv[i]) + 1;
+
+ len *= sizeof (*argp);
+ loaded_image->LoadOptions = argp = malloc (len);
+ if (loaded_image->LoadOptions == NULL) {
+ (void) BS->UnloadImage(loaded_image);
+ return (CMD_ERROR);
+ }
+ loaded_image->LoadOptionsSize = len;
+ for (i = 2; i < argc; i++) {
+ char *ptr = argv[i];
+ while (*ptr)
+ *(argp++) = *(ptr++);
+ *(argp++) = ' ';
+ }
+ *(--argv) = 0;
+ }
+
+ if (efi_getdev((void **)&dev, name, (const char **)&path) == 0)
+ loaded_image->DeviceHandle =
+ efi_find_handle(dev->d_dev, dev->d_unit);
+
+ dev_cleanup();
+ status = BS->StartImage(loaderhandle, NULL, NULL);
+ if (status != EFI_SUCCESS) {
+ command_errmsg = "StartImage failed";
+ free(loaded_image->LoadOptions);
+ loaded_image->LoadOptions = NULL;
+ status = BS->UnloadImage(loaded_image);
+ return (CMD_ERROR);
+ }
+
+ return (CMD_ERROR); /* not reached */
+}
+
+COMMAND_SET(chain, "chain", "chain load file", command_chain);
+
#ifdef EFI_ZFS_BOOT
static void
efi_zfs_probe(void)