Add support for booting kernels from FFS partitions.
This commit is contained in:
parent
fd609622b3
commit
d8588d7597
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile.efiboot,v 1.1 2018/08/24 02:01:06 jmcneill Exp $
|
||||
# $NetBSD: Makefile.efiboot,v 1.2 2018/08/26 21:28:18 jmcneill Exp $
|
||||
|
||||
S= ${.CURDIR}/../../..
|
||||
|
||||
|
@ -22,7 +22,7 @@ AFLAGS.start.S= ${${ACTIVE_CC} == "clang":?-no-integrated-as:}
|
|||
.PATH: ${EFIDIR}/gnuefi
|
||||
SOURCES= crt0-efi-${GNUEFIARCH}.S reloc_${GNUEFIARCH}.c
|
||||
SOURCES+= boot.c conf.c console.c devopen.c exec.c panic.c prompt.c
|
||||
SOURCES+= efiboot.c efichar.c efifdt.c efifile.c
|
||||
SOURCES+= efiboot.c efichar.c efidev.c efifdt.c efifile.c efiblock.c
|
||||
|
||||
.PATH: ${S}/external/bsd/libfdt/dist
|
||||
CPPFLAGS+= -I${S}/external/bsd/libfdt/dist
|
||||
|
@ -74,7 +74,7 @@ CPPFLAGS+= -D"devb2cdb(bno)=(bno)"
|
|||
#CPPFLAGS+= -DSUPPORT_DHCP
|
||||
#CPPFLAGS+= -DSUPPORT_NFS
|
||||
#CPPFLAGS+= -DSUPPORT_TFTP
|
||||
#CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
|
||||
CPPFLAGS+= -DLIBSA_ENABLE_LS_OP
|
||||
|
||||
#CPPFLAGS+= -DARP_DEBUG
|
||||
#CPPFLAGS+= -DBOOTP_DEBUG
|
||||
|
@ -93,7 +93,7 @@ SA_AS= library
|
|||
SAMISCMAKEFLAGS+="SA_USE_LOADFILE=yes"
|
||||
SAMISCMAKEFLAGS+="SA_USE_CREAD=yes"
|
||||
#SAMISCMAKEFLAGS+="SA_INCLUDE_NET=yes"
|
||||
#SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
|
||||
SAMISCMAKEFLAGS+="SA_ENABLE_LS_OP=yes"
|
||||
.include "${S}/lib/libsa/Makefile.inc"
|
||||
LIBSA= ${SALIB}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: boot.c,v 1.2 2018/08/24 23:22:10 jmcneill Exp $ */
|
||||
/* $NetBSD: boot.c,v 1.3 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 Kimihiro Nonaka <nonaka@netbsd.org>
|
||||
|
@ -28,6 +28,7 @@
|
|||
*/
|
||||
|
||||
#include "efiboot.h"
|
||||
#include "efiblock.h"
|
||||
|
||||
#include <sys/bootblock.h>
|
||||
#include <sys/boot_flag.h>
|
||||
|
@ -40,9 +41,9 @@ extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
|
|||
extern char twiddle_toggle;
|
||||
|
||||
static const char * const names[][2] = {
|
||||
{ "\\netbsd", "\\netbsd.gz" },
|
||||
{ "\\onetbsd", "\\onetbsd.gz" },
|
||||
{ "\\netbsd.old", "\\netbsd.old.gz" },
|
||||
{ "netbsd", "netbsd.gz" },
|
||||
{ "onetbsd", "onetbsd.gz" },
|
||||
{ "netbsd.old", "netbsd.old.gz" },
|
||||
};
|
||||
|
||||
#define NUMNAMES __arraycount(names)
|
||||
|
@ -50,13 +51,19 @@ static const char * const names[][2] = {
|
|||
|
||||
#define DEFTIMEOUT 5
|
||||
|
||||
static char default_device[32];
|
||||
|
||||
void command_boot(char *);
|
||||
void command_dev(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\"" },
|
||||
{ "dev", command_dev, "dev" },
|
||||
{ "ls", command_ls, "ls [hdNn:/path]\n" },
|
||||
{ "version", command_version, "version" },
|
||||
{ "help", command_help, "help|?" },
|
||||
{ "?", command_help, NULL },
|
||||
|
@ -85,6 +92,27 @@ command_boot(char *arg)
|
|||
exec_netbsd(*fname ? fname : DEFFILENAME, bootargs);
|
||||
}
|
||||
|
||||
void
|
||||
command_dev(char *arg)
|
||||
{
|
||||
if (arg && *arg) {
|
||||
set_default_device(arg);
|
||||
} else {
|
||||
efi_block_show();
|
||||
}
|
||||
|
||||
if (strlen(default_device) > 0) {
|
||||
printf("\n");
|
||||
printf("default: %s\n", default_device);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
command_ls(char *arg)
|
||||
{
|
||||
ls(arg);
|
||||
}
|
||||
|
||||
void
|
||||
command_version(char *arg)
|
||||
{
|
||||
|
@ -109,6 +137,21 @@ command_quit(char *arg)
|
|||
efi_exit();
|
||||
}
|
||||
|
||||
int
|
||||
set_default_device(char *arg)
|
||||
{
|
||||
if (strlen(arg) + 1 > sizeof(default_device))
|
||||
return ERANGE;
|
||||
strcpy(default_device, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
get_default_device(void)
|
||||
{
|
||||
return default_device;
|
||||
}
|
||||
|
||||
void
|
||||
print_banner(void)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: conf.c,v 1.1 2018/08/24 02:01:06 jmcneill Exp $ */
|
||||
/* $NetBSD: conf.c,v 1.2 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||
|
@ -28,9 +28,15 @@
|
|||
|
||||
#include "efiboot.h"
|
||||
#include "efifile.h"
|
||||
#include "efiblock.h"
|
||||
|
||||
#include <lib/libsa/stand.h>
|
||||
#include <lib/libsa/ufs.h>
|
||||
#include <lib/libsa/dosfs.h>
|
||||
|
||||
struct devsw devsw[] = {
|
||||
{ "efifile", efi_file_strategy, efi_file_open, efi_file_close, noioctl },
|
||||
{ "efiblock", efi_block_strategy, efi_block_open, efi_block_close, noioctl },
|
||||
};
|
||||
int ndevs = __arraycount(devsw);
|
||||
|
||||
|
@ -39,5 +45,8 @@ struct netif_driver *netif_drivers[] = {
|
|||
int n_netif_drivers = __arraycount(netif_drivers);
|
||||
|
||||
struct fs_ops file_system[] = {
|
||||
FS_OPS(ffsv1),
|
||||
FS_OPS(ffsv2),
|
||||
FS_OPS(dosfs),
|
||||
};
|
||||
int nfsys = __arraycount(file_system);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: devopen.c,v 1.1 2018/08/24 02:01:06 jmcneill Exp $ */
|
||||
/* $NetBSD: devopen.c,v 1.2 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||
|
@ -28,13 +28,16 @@
|
|||
|
||||
#include "efiboot.h"
|
||||
#include "efifile.h"
|
||||
#include "efiblock.h"
|
||||
|
||||
int
|
||||
devopen(struct open_file *f, const char *fname, char **file)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = efi_file_open(f, fname);
|
||||
error = efi_block_open(f, fname, file);
|
||||
if (error)
|
||||
error = efi_file_open(f, fname);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
/* $NetBSD: efiblock.c,v 1.1 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 Kimihiro Nonaka <nonaka@netbsd.org>
|
||||
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define FSTYPENAMES
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "efiboot.h"
|
||||
#include "efiblock.h"
|
||||
|
||||
static EFI_HANDLE *efi_block;
|
||||
static UINTN efi_nblock;
|
||||
|
||||
static TAILQ_HEAD(, efi_block_dev) efi_block_devs = TAILQ_HEAD_INITIALIZER(efi_block_devs);
|
||||
|
||||
static int
|
||||
efi_block_parse(const char *fname, struct efi_block_part **pbpart, char **pfile)
|
||||
{
|
||||
struct efi_block_dev *bdev;
|
||||
struct efi_block_part *bpart;
|
||||
char pathbuf[PATH_MAX], *default_device, *ep = NULL;
|
||||
const char *full_path;
|
||||
intmax_t dev;
|
||||
int part;
|
||||
|
||||
default_device = get_default_device();
|
||||
if (strchr(fname, ':') == NULL) {
|
||||
if (strlen(default_device) > 0) {
|
||||
snprintf(pathbuf, sizeof(pathbuf), "%s:%s", default_device, fname);
|
||||
full_path = pathbuf;
|
||||
*pfile = __UNCONST(fname);
|
||||
} else {
|
||||
return EINVAL;
|
||||
}
|
||||
} else {
|
||||
full_path = fname;
|
||||
*pfile = strchr(fname, ':') + 1;
|
||||
}
|
||||
|
||||
if (strncasecmp(full_path, "hd", 2) != 0)
|
||||
return EINVAL;
|
||||
dev = strtoimax(full_path + 2, &ep, 10);
|
||||
if (dev < 0 || dev >= efi_nblock)
|
||||
return ENXIO;
|
||||
if (ep[0] < 'a' || ep[0] >= 'a' + MAXPARTITIONS || ep[1] != ':')
|
||||
return EINVAL;
|
||||
part = ep[0] - 'a';
|
||||
TAILQ_FOREACH(bdev, &efi_block_devs, entries) {
|
||||
if (bdev->index == dev) {
|
||||
TAILQ_FOREACH(bpart, &bdev->partitions, entries) {
|
||||
if (bpart->index == part) {
|
||||
*pbpart = bpart;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
static int
|
||||
efi_block_find_partitions_disklabel(struct efi_block_dev *bdev, uint32_t start, uint32_t size)
|
||||
{
|
||||
struct efi_block_part *bpart;
|
||||
struct disklabel d;
|
||||
struct partition *p;
|
||||
EFI_STATUS status;
|
||||
EFI_LBA lba;
|
||||
uint8_t *buf;
|
||||
UINT32 sz;
|
||||
int n;
|
||||
|
||||
sz = __MAX(sizeof(d), bdev->bio->Media->BlockSize);
|
||||
sz = roundup(sz, bdev->bio->Media->BlockSize);
|
||||
buf = AllocatePool(sz);
|
||||
if (!buf)
|
||||
return ENOMEM;
|
||||
|
||||
lba = ((start + LABELSECTOR) * DEV_BSIZE) / bdev->bio->Media->BlockSize;
|
||||
status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, lba, sz, buf);
|
||||
if (EFI_ERROR(status) || getdisklabel(buf, &d) != NULL) {
|
||||
FreePool(buf);
|
||||
return EIO;
|
||||
}
|
||||
FreePool(buf);
|
||||
|
||||
if (le32toh(d.d_magic) != DISKMAGIC || le32toh(d.d_magic2) != DISKMAGIC)
|
||||
return EINVAL;
|
||||
if (le16toh(d.d_npartitions) > MAXPARTITIONS)
|
||||
return EINVAL;
|
||||
|
||||
for (n = 0; n < le16toh(d.d_npartitions); n++) {
|
||||
p = &d.d_partitions[n];
|
||||
switch (p->p_fstype) {
|
||||
case FS_BSDFFS:
|
||||
case FS_MSDOS:
|
||||
case FS_BSDLFS:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
bpart = alloc(sizeof(*bpart));
|
||||
bpart->index = n;
|
||||
bpart->bdev = bdev;
|
||||
bpart->type = EFI_BLOCK_PART_DISKLABEL;
|
||||
bpart->disklabel.secsize = le32toh(d.d_secsize);
|
||||
bpart->disklabel.part = *p;
|
||||
TAILQ_INSERT_TAIL(&bdev->partitions, bpart, entries);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
efi_block_find_partitions_mbr(struct efi_block_dev *bdev)
|
||||
{
|
||||
struct mbr_sector mbr;
|
||||
struct mbr_partition *mbr_part;
|
||||
EFI_STATUS status;
|
||||
uint8_t *buf;
|
||||
UINT32 sz;
|
||||
int n;
|
||||
|
||||
sz = __MAX(sizeof(mbr), bdev->bio->Media->BlockSize);
|
||||
sz = roundup(sz, bdev->bio->Media->BlockSize);
|
||||
buf = AllocatePool(sz);
|
||||
if (!buf)
|
||||
return ENOMEM;
|
||||
|
||||
status = uefi_call_wrapper(bdev->bio->ReadBlocks, 5, bdev->bio, bdev->media_id, 0, sz, buf);
|
||||
if (EFI_ERROR(status)) {
|
||||
FreePool(buf);
|
||||
return EIO;
|
||||
}
|
||||
memcpy(&mbr, buf, sizeof(mbr));
|
||||
FreePool(buf);
|
||||
|
||||
if (le32toh(mbr.mbr_magic) != MBR_MAGIC)
|
||||
return ENOENT;
|
||||
|
||||
for (n = 0; n < MBR_PART_COUNT; n++) {
|
||||
mbr_part = &mbr.mbr_parts[n];
|
||||
if (le32toh(mbr_part->mbrp_size) == 0)
|
||||
continue;
|
||||
if (mbr_part->mbrp_type == MBR_PTYPE_NETBSD) {
|
||||
efi_block_find_partitions_disklabel(bdev, le32toh(mbr_part->mbrp_start), le32toh(mbr_part->mbrp_size));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
efi_block_find_partitions(struct efi_block_dev *bdev)
|
||||
{
|
||||
return efi_block_find_partitions_mbr(bdev);
|
||||
}
|
||||
|
||||
void
|
||||
efi_block_probe(void)
|
||||
{
|
||||
struct efi_block_dev *bdev;
|
||||
EFI_BLOCK_IO *bio;
|
||||
EFI_STATUS status;
|
||||
uint16_t devindex = 0;
|
||||
int depth = -1;
|
||||
int n;
|
||||
|
||||
status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL, &efi_nblock, &efi_block);
|
||||
if (EFI_ERROR(status))
|
||||
return;
|
||||
|
||||
if (efi_bootdp) {
|
||||
depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH);
|
||||
if (depth == 0)
|
||||
depth = 1;
|
||||
}
|
||||
|
||||
for (n = 0; n < efi_nblock; n++) {
|
||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, efi_block[n], &BlockIoProtocol, (void **)&bio);
|
||||
if (EFI_ERROR(status) || !bio->Media->MediaPresent)
|
||||
continue;
|
||||
|
||||
if (bio->Media->LogicalPartition)
|
||||
continue;
|
||||
|
||||
bdev = alloc(sizeof(*bdev));
|
||||
bdev->index = devindex++;
|
||||
bdev->bio = bio;
|
||||
bdev->media_id = bio->Media->MediaId;
|
||||
bdev->path = DevicePathFromHandle(efi_block[n]);
|
||||
TAILQ_INIT(&bdev->partitions);
|
||||
TAILQ_INSERT_TAIL(&efi_block_devs, bdev, entries);
|
||||
|
||||
if (depth > 0 && efi_device_path_ncmp(efi_bootdp, DevicePathFromHandle(efi_block[n]), depth) == 0) {
|
||||
char devname[9];
|
||||
snprintf(devname, sizeof(devname), "hd%ua", bdev->index);
|
||||
set_default_device(devname);
|
||||
}
|
||||
|
||||
efi_block_find_partitions(bdev);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
efi_block_show(void)
|
||||
{
|
||||
struct efi_block_dev *bdev;
|
||||
struct efi_block_part *bpart;
|
||||
uint64_t size;
|
||||
CHAR16 *path;
|
||||
|
||||
TAILQ_FOREACH(bdev, &efi_block_devs, entries) {
|
||||
printf("hd%u (", bdev->index);
|
||||
|
||||
/* Size in MB */
|
||||
size = ((bdev->bio->Media->LastBlock + 1) * bdev->bio->Media->BlockSize) / (1024 * 1024);
|
||||
if (size >= 10000)
|
||||
printf("%"PRIu64" GB", size / 1024);
|
||||
else
|
||||
printf("%"PRIu64" MB", size);
|
||||
printf("): ");
|
||||
|
||||
path = DevicePathToStr(bdev->path);
|
||||
Print(L"%s", path);
|
||||
FreePool(path);
|
||||
|
||||
printf("\n");
|
||||
|
||||
TAILQ_FOREACH(bpart, &bdev->partitions, entries) {
|
||||
switch (bpart->type) {
|
||||
case EFI_BLOCK_PART_DISKLABEL:
|
||||
printf(" hd%u%c (", bdev->index, bpart->index + 'a');
|
||||
|
||||
/* Size in MB */
|
||||
size = ((uint64_t)bpart->disklabel.secsize * bpart->disklabel.part.p_size) / (1024 * 1024);
|
||||
if (size >= 10000)
|
||||
printf("%"PRIu64" GB", size / 1024);
|
||||
else
|
||||
printf("%"PRIu64" MB", size);
|
||||
printf("): ");
|
||||
|
||||
printf("%s\n", fstypenames[bpart->disklabel.part.p_fstype]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
efi_block_open(struct open_file *f, ...)
|
||||
{
|
||||
struct efi_block_part *bpart;
|
||||
const char *fname;
|
||||
char **file;
|
||||
char *path;
|
||||
va_list ap;
|
||||
int rv, n;
|
||||
|
||||
va_start(ap, f);
|
||||
fname = va_arg(ap, const char *);
|
||||
file = va_arg(ap, char **);
|
||||
va_end(ap);
|
||||
|
||||
rv = efi_block_parse(fname, &bpart, &path);
|
||||
if (rv != 0)
|
||||
return rv;
|
||||
|
||||
for (n = 0; n < ndevs; n++)
|
||||
if (strcmp(DEV_NAME(&devsw[n]), "efiblock") == 0) {
|
||||
f->f_dev = &devsw[n];
|
||||
break;
|
||||
}
|
||||
if (n == ndevs)
|
||||
return ENXIO;
|
||||
|
||||
f->f_devdata = bpart;
|
||||
|
||||
*file = path;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
efi_block_close(struct open_file *f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
efi_block_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
|
||||
{
|
||||
struct efi_block_part *bpart = devdata;
|
||||
EFI_STATUS status;
|
||||
|
||||
if (rw != F_READ)
|
||||
return EROFS;
|
||||
|
||||
switch (bpart->type) {
|
||||
case EFI_BLOCK_PART_DISKLABEL:
|
||||
if (bpart->bdev->bio->Media->BlockSize != bpart->disklabel.secsize) {
|
||||
printf("%s: unsupported block size %d (expected %d)\n", __func__,
|
||||
bpart->bdev->bio->Media->BlockSize, bpart->disklabel.secsize);
|
||||
return EIO;
|
||||
}
|
||||
dblk += bpart->disklabel.part.p_offset;
|
||||
break;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
status = uefi_call_wrapper(bpart->bdev->bio->ReadBlocks, 5, bpart->bdev->bio, bpart->bdev->media_id, dblk, size, buf);
|
||||
if (EFI_ERROR(status))
|
||||
return EIO;
|
||||
|
||||
*rsize = size;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* $NetBSD: efiblock.h,v 1.1 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/bootblock.h>
|
||||
#include <sys/disklabel.h>
|
||||
|
||||
enum efi_block_part_type {
|
||||
EFI_BLOCK_PART_DISKLABEL,
|
||||
EFI_BLOCK_PART_GPT
|
||||
};
|
||||
|
||||
struct efi_block_part;
|
||||
|
||||
struct efi_block_dev {
|
||||
uint16_t index;
|
||||
EFI_DEVICE_PATH *path;
|
||||
EFI_BLOCK_IO *bio;
|
||||
UINT32 media_id;
|
||||
TAILQ_HEAD(, efi_block_part) partitions;
|
||||
|
||||
TAILQ_ENTRY(efi_block_dev) entries;
|
||||
};
|
||||
|
||||
struct efi_block_part_disklabel {
|
||||
uint32_t secsize;
|
||||
struct partition part;
|
||||
};
|
||||
|
||||
struct efi_block_part {
|
||||
uint32_t index;
|
||||
struct efi_block_dev *bdev;
|
||||
enum efi_block_part_type type;
|
||||
union {
|
||||
struct efi_block_part_disklabel disklabel;
|
||||
};
|
||||
|
||||
TAILQ_ENTRY(efi_block_part) entries;
|
||||
};
|
||||
|
||||
void efi_block_probe(void);
|
||||
void efi_block_show(void);
|
||||
|
||||
int efi_block_open(struct open_file *, ...);
|
||||
int efi_block_close(struct open_file *);
|
||||
int efi_block_strategy(void *, int, daddr_t, size_t, void *, size_t *);
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: efiboot.c,v 1.3 2018/08/24 23:21:56 jmcneill Exp $ */
|
||||
/* $NetBSD: efiboot.c,v 1.4 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "efiboot.h"
|
||||
#include "efifile.h"
|
||||
#include "efiblock.h"
|
||||
#include "efifdt.h"
|
||||
|
||||
EFI_HANDLE efi_ih;
|
||||
|
@ -74,6 +75,7 @@ efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
|
|||
|
||||
efi_fdt_probe();
|
||||
efi_file_system_probe();
|
||||
efi_block_probe();
|
||||
|
||||
boot();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: efiboot.h,v 1.1 2018/08/24 02:01:06 jmcneill Exp $ */
|
||||
/* $NetBSD: efiboot.h,v 1.2 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 Kimihiro Nonaka <nonaka@netbsd.org>
|
||||
|
@ -46,6 +46,8 @@ void clearit(void);
|
|||
void print_banner(void);
|
||||
extern const struct boot_command commands[];
|
||||
void command_help(char *);
|
||||
int set_default_device(char *);
|
||||
char *get_default_device(void);
|
||||
|
||||
/* console.c */
|
||||
int ischar(void);
|
||||
|
@ -63,6 +65,10 @@ size_t ucs2len(const CHAR16 *);
|
|||
int ucs2_to_utf8(const CHAR16 *, char **);
|
||||
int utf8_to_ucs2(const char *, CHAR16 **, size_t *);
|
||||
|
||||
/* efidev.c */
|
||||
int efi_device_path_depth(EFI_DEVICE_PATH *dp, int);
|
||||
int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int);
|
||||
|
||||
/* exec.c */
|
||||
int exec_netbsd(const char *, const char *);
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* $NetBSD: efidev.c,v 1.1 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
/* $OpenBSD: efiboot.c,v 1.28 2017/11/25 19:02:07 patrick Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "efiboot.h"
|
||||
|
||||
/*
|
||||
* Determine the number of nodes up to, but not including, the first
|
||||
* node of the specified type.
|
||||
*/
|
||||
int
|
||||
efi_device_path_depth(EFI_DEVICE_PATH *dp, int dptype)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp), i++) {
|
||||
if (DevicePathType(dp) == dptype)
|
||||
return (i);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
efi_device_path_ncmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int deptn)
|
||||
{
|
||||
int i, cmp;
|
||||
|
||||
for (i = 0; i < deptn; i++) {
|
||||
if (IsDevicePathEnd(dpa) || IsDevicePathEnd(dpb))
|
||||
return ((IsDevicePathEnd(dpa) && IsDevicePathEnd(dpb))
|
||||
? 0 : (IsDevicePathEnd(dpa))? -1 : 1);
|
||||
cmp = DevicePathNodeLength(dpa) - DevicePathNodeLength(dpb);
|
||||
if (cmp)
|
||||
return (cmp);
|
||||
cmp = memcmp(dpa, dpb, DevicePathNodeLength(dpa));
|
||||
if (cmp)
|
||||
return (cmp);
|
||||
dpa = NextDevicePathNode(dpa);
|
||||
dpb = NextDevicePathNode(dpb);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: efifile.c,v 1.2 2018/08/24 23:19:42 jmcneill Exp $ */
|
||||
/* $NetBSD: efifile.c,v 1.3 2018/08/26 21:28:18 jmcneill Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
|
||||
|
@ -33,7 +33,6 @@
|
|||
|
||||
static EFI_HANDLE *efi_vol;
|
||||
static UINTN efi_nvol;
|
||||
static int efi_bootvol = -1;
|
||||
|
||||
static int
|
||||
efi_file_parse(const char *fname, UINTN *pvol, const char **pfile)
|
||||
|
@ -49,37 +48,20 @@ efi_file_parse(const char *fname, UINTN *pvol, const char **pfile)
|
|||
return ENXIO;
|
||||
*pvol = vol;
|
||||
*pfile = ep + 1;
|
||||
} else if (efi_bootvol != -1) {
|
||||
*pvol = efi_bootvol;
|
||||
*pfile = fname;
|
||||
} else {
|
||||
return EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
void
|
||||
efi_file_system_probe(void)
|
||||
{
|
||||
EFI_FILE_HANDLE fh;
|
||||
EFI_STATUS status;
|
||||
int n;
|
||||
|
||||
status = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &efi_nvol, &efi_vol);
|
||||
if (EFI_ERROR(status))
|
||||
return;
|
||||
|
||||
for (n = 0; n < efi_nvol; n++) {
|
||||
fh = LibOpenRoot(efi_vol[n]);
|
||||
if (!fh)
|
||||
continue;
|
||||
|
||||
if (efi_bootdp && LibMatchDevicePaths(DevicePathFromHandle(efi_vol[n]), efi_bootdp) == TRUE)
|
||||
efi_bootvol = n;
|
||||
else if (efi_bootdp == NULL && efi_bootvol == -1)
|
||||
efi_bootvol = n;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -94,7 +76,7 @@ efi_file_open(struct open_file *f, ...)
|
|||
CHAR16 *upath;
|
||||
va_list ap;
|
||||
size_t len;
|
||||
int rv;
|
||||
int rv, n;
|
||||
|
||||
va_start(ap, f);
|
||||
fname = va_arg(ap, const char *);
|
||||
|
@ -121,7 +103,13 @@ efi_file_open(struct open_file *f, ...)
|
|||
if (EFI_ERROR(status))
|
||||
return status == EFI_NOT_FOUND ? ENOENT : EIO;
|
||||
|
||||
f->f_dev = &devsw[0];
|
||||
for (n = 0; n < ndevs; n++)
|
||||
if (strcmp(DEV_NAME(&devsw[n]), "efifile") == 0) {
|
||||
f->f_dev = &devsw[n];
|
||||
break;
|
||||
}
|
||||
if (n == ndevs)
|
||||
return ENXIO;
|
||||
f->f_devdata = f;
|
||||
f->f_fsdata = srf;
|
||||
f->f_flags = F_NODEV | F_READ;
|
||||
|
|
Loading…
Reference in New Issue