Index: sys/arch/i386/stand/boot/boot2.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/boot/boot2.c,v retrieving revision 1.70 diff -U4 -r1.70 boot2.c --- sys/arch/i386/stand/boot/boot2.c 14 Nov 2017 09:55:41 -0000 1.70 +++ sys/arch/i386/stand/boot/boot2.c 10 Aug 2019 01:47:34 -0000 @@ -103,9 +103,13 @@ #define NUMNAMES (sizeof(names)/sizeof(names[0])) #define DEFFILENAME names[0][0] +#ifndef NO_GPT +#define MAXDEVNAME 39 /* "NAME=" + 34 char part_name */ +#else #define MAXDEVNAME 16 +#endif static char *default_devname; static int default_unit, default_partition; static const char *default_filename; @@ -179,8 +183,19 @@ devlen = col - fname; if (devlen > MAXDEVNAME) return EINVAL; +#ifndef NO_GPT + if (strstr(fname, "NAME=") == fname) { + strlcpy(savedevname, fname, devlen + 1); + *devname = savedevname; + *unit = -1; + *partition = -1; + fname = col + 1; + goto out; + } +#endif + #define isvalidname(c) ((c) >= 'a' && (c) <= 'z') if (!isvalidname(fname[i])) return EINVAL; do { @@ -214,8 +229,9 @@ *partition = p; fname = col + 1; } +out: if (*fname) *file = fname; return 0; Index: sys/arch/i386/stand/boot/devopen.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/boot/devopen.c,v retrieving revision 1.8 diff -U4 -r1.8 devopen.c --- sys/arch/i386/stand/boot/devopen.c 24 Dec 2010 20:40:42 -0000 1.8 +++ sys/arch/i386/stand/boot/devopen.c 10 Aug 2019 01:47:34 -0000 @@ -127,11 +127,11 @@ int unit, partition; int biosdev; int error; - if ((error = parsebootfile(fname, &fsname, &devname, - &unit, &partition, (const char **) file)) - || (error = dev2bios(devname, unit, &biosdev))) + error = parsebootfile(fname, &fsname, &devname, + &unit, &partition, (const char **) file); + if (error) return error; f->f_dev = &devsw[0]; /* must be biosdisk */ @@ -141,6 +141,27 @@ BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); } #endif +#ifndef NO_GPT + /* Search by GPT label name */ + if (strstr(devname, "NAME=") == devname) { + f->f_dev = &devsw[0]; /* must be biosdisk */ + + return biosdisk_open_name(f, fname); + } +#endif +#ifndef NO_RAIDFRAME + /* Search by raidframe name */ + if (strstr(devname, "raid") == devname) { + f->f_dev = &devsw[0]; /* must be biosdisk */ + + return biosdisk_open_name(f, fname); + } +#endif + + error = dev2bios(devname, unit, &biosdev); + if (error) + return error; + return biosdisk_open(f, biosdev, partition); } Index: sys/arch/i386/stand/efiboot/boot.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/efiboot/boot.c,v retrieving revision 1.11 diff -U4 -r1.11 boot.c --- sys/arch/i386/stand/efiboot/boot.c 20 Jun 2019 17:33:31 -0000 1.11 +++ sys/arch/i386/stand/efiboot/boot.c 10 Aug 2019 01:47:34 -0000 @@ -141,8 +141,17 @@ devlen = col - fname; if (devlen > MAXDEVNAME) return EINVAL; + if (strstr(fname, "NAME=") == fname) { + strlcpy(savedevname, fname, devlen + 1); + *devname = savedevname; + *unit = -1; + *partition = -1; + fname = col + 1; + goto out; + } + #define isvalidname(c) ((c) >= 'a' && (c) <= 'z') if (!isvalidname(fname[i])) return EINVAL; do { @@ -176,8 +185,9 @@ *partition = p; fname = col + 1; } +out: if (*fname) *file = fname; return 0; Index: sys/arch/i386/stand/efiboot/devopen.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/efiboot/devopen.c,v retrieving revision 1.5 diff -U4 -r1.5 devopen.c --- sys/arch/i386/stand/efiboot/devopen.c 11 Apr 2018 10:32:09 -0000 1.5 +++ sys/arch/i386/stand/efiboot/devopen.c 10 Aug 2019 01:47:34 -0000 @@ -129,8 +129,22 @@ (const char **) file); if (error) return error; + /* Search by GPT label or raidframe name */ + if ((strstr(devname, "NAME=") == devname) || + (strstr(devname, "raid") == devname)) { + f->f_dev = &devsw[0]; /* must be biosdisk */ + + if (!kernel_loaded) { + strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath)); + BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); + } + + error = biosdisk_open_name(f, fname); + return error; + } + memcpy(file_system, file_system_disk, sizeof(*file_system) * nfsys); nfsys = nfsys_disk; #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP) Index: sys/arch/i386/stand/efiboot/devopen.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/efiboot/devopen.h,v retrieving revision 1.3 diff -U4 -r1.3 devopen.h --- sys/arch/i386/stand/efiboot/devopen.h 11 Apr 2018 10:32:09 -0000 1.3 +++ sys/arch/i386/stand/efiboot/devopen.h 10 Aug 2019 01:47:34 -0000 @@ -33,9 +33,9 @@ extern struct fs_ops file_system_nfs; extern struct fs_ops file_system_tftp; extern struct fs_ops file_system_null; -#define MAXDEVNAME 16 +#define MAXDEVNAME 39 /* mxmimum is "NAME=" + 34 char part_name */ void bios2dev(int, daddr_t, char **, int *, int *); struct devdesc { Index: sys/arch/i386/stand/efiboot/efidisk.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/efiboot/efidisk.c,v retrieving revision 1.7 diff -U4 -r1.7 efidisk.c --- sys/arch/i386/stand/efiboot/efidisk.c 17 Apr 2019 06:50:34 -0000 1.7 +++ sys/arch/i386/stand/efiboot/efidisk.c 10 Aug 2019 01:47:34 -0000 @@ -29,9 +29,11 @@ #define FSTYPENAMES /* for sys/disklabel.h */ #include "efiboot.h" +#include /* for howmany, required by */ #include +#include #include "biosdisk.h" #include "biosdisk_ll.h" #include "devopen.h" @@ -39,8 +41,42 @@ static struct efidiskinfo_lh efi_disklist; static int nefidisks; +#define MAXDEVNAME 39 /* "NAME=" + 34 char part_name */ + +#include +#define RF_COMPONENT_INFO_OFFSET 16384 /* from sys/dev/raidframe/rf_netbsdkintf.c */ +#define RF_COMPONENT_LABEL_VERSION 2 /* from */ + +#define RAIDFRAME_NDEV 16 /* abitrary limit to 15 raidframe devices */ +struct efi_raidframe { + int last_unit; + int serial; + const struct efidiskinfo *edi; + int parent_part; + char parent_name[MAXDEVNAME + 1]; + daddr_t offset; + daddr_t size; +}; + +static void +dealloc_biosdisk_part(struct biosdisk_partition *part, int nparts) +{ + int i; + + for (i = 0; i < nparts; i++) { + if (part[i].part_name != NULL) { + dealloc(part[i].part_name, BIOSDISK_PART_NAME_LEN); + part[i].part_name = NULL; + } + } + + dealloc(part, sizeof(*part) * nparts); + + return; +} + void efi_disk_probe(void) { EFI_STATUS status; @@ -123,16 +159,53 @@ boot_biosdev = edi->dev; } } +static void +efi_raidframe_probe(struct efi_raidframe *raidframe, int *raidframe_count, + const struct efidiskinfo *edi, + struct biosdisk_partition *part, int parent_part) + +{ + int i = *raidframe_count; + struct RF_ComponentLabel_s label; + + if (i + 1 > RAIDFRAME_NDEV) + return; + + if (biosdisk_read_raidframe(edi->dev, part->offset, &label) != 0) + return; + + if (label.version != RF_COMPONENT_LABEL_VERSION) + return; + + raidframe[i].last_unit = label.last_unit; + raidframe[i].serial = label.serial_number; + raidframe[i].edi = edi; + raidframe[i].parent_part = parent_part; + if (part->part_name) + strlcpy(raidframe[i].parent_name, part->part_name, MAXDEVNAME); + else + raidframe[i].parent_name[0] = '\0'; + raidframe[i].offset = part->offset; + raidframe[i].size = label.__numBlocks; + + (*raidframe_count)++; + + return; +} + + void efi_disk_show(void) { const struct efidiskinfo *edi; + struct efi_raidframe raidframe[RAIDFRAME_NDEV]; + int raidframe_count = 0; EFI_BLOCK_IO_MEDIA *media; struct biosdisk_partition *part; uint64_t size; - int i, nparts; + int i, j, nparts; bool first; TAILQ_FOREACH(edi, &efi_disklist, list) { media = edi->bio->Media; @@ -163,21 +236,28 @@ } if (edi->type != BIOSDISK_TYPE_HD) continue; - if (biosdisk_readpartition(edi->dev, &part, &nparts)) + if (biosdisk_readpartition(edi->dev, 0, 0, &part, &nparts)) continue; for (i = 0; i < nparts; i++) { if (part[i].size == 0) continue; if (part[i].fstype == FS_UNUSED) continue; + if (part[i].fstype == FS_RAID) { + efi_raidframe_probe(raidframe, &raidframe_count, + edi, &part[i], i); + } if (first) { printf(" "); first = false; } - printf(" hd%d%c(", edi->dev & 0x7f, i + 'a'); + if (part[i].part_name != NULL) + printf(" NAME=%s(", part[i].part_name); + else + printf(" hd%d%c(", edi->dev & 0x7f, i + 'a'); if (part[i].guid != NULL) printf("%s", part[i].guid->name); else if (part[i].fstype < FSMAXTYPES) printf("%s", fstypenames[part[i].fstype]); @@ -186,9 +266,68 @@ printf(")"); } if (!first) printf("\n"); - dealloc(part, sizeof(*part) * nparts); + dealloc_biosdisk_part(part, nparts); + } + + for (i = 0; i < raidframe_count; i++) { + size_t secsize = raidframe[i].edi->bio->Media->BlockSize; + printf("raidframe raid%d serial %d in ", + raidframe[i].last_unit, raidframe[i].serial); + if (raidframe[i].parent_name[0]) + printf("NAME=%s size ", raidframe[i].parent_name); + else + printf("hd%d%c size ", + raidframe[i].edi->dev & 0x7f, + raidframe[i].parent_part + 'a'); + if (raidframe[i].size >= (10ULL * 1024 * 1024 * 1024 / secsize)) + printf("%"PRIu64" GB", + raidframe[i].size / (1024 * 1024 * 1024 / secsize)); + else + printf("%"PRIu64" MB", + raidframe[i].size / (1024 * 1024 / secsize)); + printf("\n"); + + if (biosdisk_readpartition(raidframe[i].edi->dev, + raidframe[i].offset + RF_PROTECTED_SECTORS, + raidframe[i].size, + &part, &nparts)) + continue; + + first = 1; + for (j = 0; j < nparts; j++) { + bool bootme = part[j].attr & GPT_ENT_ATTR_BOOTME; + + if (part[j].size == 0) + continue; + if (part[j].fstype == FS_UNUSED) + continue; + if (part[j].fstype == FS_RAID) /* raid in raid? */ + continue; + if (first) { + printf(" "); + first = 0; + } + if (part[j].part_name != NULL) + printf(" NAME=%s(", part[j].part_name); + else + printf(" raid%d%c(", + raidframe[i].last_unit, j + 'a'); + if (part[j].guid != NULL) + printf("%s", part[j].guid->name); + else if (part[j].fstype < FSMAXTYPES) + printf("%s", + fstypenames[part[j].fstype]); + else + printf("%d", part[j].fstype); + printf("%s)", bootme ? ", bootme" : ""); + } + + if (first == 0) + printf("\n"); + + dealloc_biosdisk_part(part, nparts); } } const struct efidiskinfo * @@ -226,9 +365,9 @@ if (edi->type != BIOSDISK_TYPE_HD) return ENOTSUP; - if (biosdisk_readpartition(edi->dev, &part, &nparts)) + if (biosdisk_readpartition(edi->dev, 0, 0, &part, &nparts)) return EIO; for (i = 0; i < nparts; i++) { if (part[i].size == 0) @@ -237,9 +376,9 @@ continue; if (guid_is_equal(part[i].guid->guid, &GET_efi)) break; } - dealloc(part, sizeof(*part) * nparts); + dealloc_biosdisk_part(part, nparts); if (i == nparts) return ENOENT; *partition = i; Index: sys/arch/i386/stand/lib/biosdisk.c =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/lib/biosdisk.c,v retrieving revision 1.49 diff -U4 -r1.49 biosdisk.c --- sys/arch/i386/stand/lib/biosdisk.c 2 Apr 2018 09:44:18 -0000 1.49 +++ sys/arch/i386/stand/lib/biosdisk.c 10 Aug 2019 01:47:34 -0000 @@ -77,8 +77,9 @@ #include #include #include +#include #include #include @@ -88,8 +89,14 @@ #ifdef _STANDALONE #include "bootinfo.h" #endif +#ifndef NO_GPT +#define MAXDEVNAME 39 /* "NAME=" + 34 char part_name */ +#else +#define MAXDEVNAME 16 +#endif + #ifndef BIOSDISK_BUFSIZE #define BIOSDISK_BUFSIZE 2048 /* must be large enough for a CD sector */ #endif @@ -103,16 +110,34 @@ struct biosdisk_partition part[BIOSDISKNPART]; #endif }; +#include +#define RF_COMPONENT_INFO_OFFSET 16384 /* from sys/dev/raidframe/rf_netbsdkintf.c */ +#define RF_COMPONENT_LABEL_VERSION 2 /* from */ + +#define RAIDFRAME_NDEV 16 /* abitrary limit to 15 raidframe devices */ +struct raidframe { + int last_unit; + int serial; + int biosdev; + int parent_part; +#ifndef NO_GPT + char parent_name[MAXDEVNAME + 1]; +#endif + daddr_t offset; + daddr_t size; +}; + + #ifndef NO_GPT const struct uuid GET_nbsd_raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME; const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS; const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS; const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; const struct uuid GET_nbsd_ccd = GPT_ENT_TYPE_NETBSD_CCD; const struct uuid GET_nbsd_cgd = GPT_ENT_TYPE_NETBSD_CGD; -#ifdef EFIBOOT + const struct uuid GET_efi = GPT_ENT_TYPE_EFI; const struct uuid GET_mbr = GPT_ENT_TYPE_MBR; const struct uuid GET_fbsd = GPT_ENT_TYPE_FREEBSD; const struct uuid GET_fbsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; @@ -156,9 +181,8 @@ { &GET_apple_hfs, "Apple HFS" }, { &GET_apple_ufs, "Apple UFS" }, { &GET_bios, "BIOS Boot (GRUB)" }, }; -#endif #endif /* NO_GPT */ #ifdef _STANDALONE static struct btinfo_bootdisk bi_disk; @@ -166,14 +190,56 @@ #endif #define MBR_PARTS(buf) ((char *)(buf) + offsetof(struct mbr_sector, mbr_parts)) -#define RF_PROTECTED_SECTORS 64 /* XXX refer to <.../rf_optnames.h> */ - #ifndef devb2cdb #define devb2cdb(bno) (((bno) * DEV_BSIZE) / ISO_DEFAULT_BLOCK_SIZE) #endif +static void +dealloc_biosdisk(struct biosdisk *d) +{ +#ifndef NO_GPT + int i; + + for (i = 0; i < __arraycount(d->part); i++) { + if (d->part[i].part_name != NULL) + dealloc(d->part[i].part_name, BIOSDISK_PART_NAME_LEN); + } +#endif + + dealloc(d, sizeof(*d)); + + return; +} + +static struct biosdisk_partition * +copy_biosdisk_part(struct biosdisk *d) +{ + struct biosdisk_partition *part; + + part = alloc(sizeof(d->part)); + if (part == NULL) + goto out; + + memcpy(part, d->part, sizeof(d->part)); + +#ifndef NO_GPT + int i; + + for (i = 0; i < __arraycount(d->part); i++) { + if (d->part[i].part_name != NULL) { + part[i].part_name = alloc(BIOSDISK_PART_NAME_LEN); + memcpy(part[i].part_name, d->part[i].part_name, + BIOSDISK_PART_NAME_LEN); + } + } +#endif + +out: + return part; +} + int biosdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize) { @@ -227,9 +293,9 @@ if (set_geometry(&d->ll, NULL)) { #ifdef DISK_DEBUG printf("no geometry information\n"); #endif - dealloc(d, sizeof(*d)); + dealloc_biosdisk(d); return NULL; } return d; } @@ -261,10 +327,35 @@ { return (memcmp(a, b, sizeof(*a)) == 0 ? true : false); } +#ifndef NO_GPT +static void +part_name_utf8(const uint16_t *utf16_src, size_t utf16_srclen, + char *utf8_dst, size_t utf8_dstlen) +{ + char *c = utf8_dst; + size_t r = utf8_dstlen - 1; + size_t n; + int j; + + if (utf8_dst == NULL) + return; + + for (j = 0; j < utf16_srclen && utf16_src[j] != 0x0000; j++) { + n = wput_utf8(c, r, le16toh(utf16_src[j])); + if (n == 0) + break; + c += n; r -= n; + } + *c = '\0'; + + return; +} +#endif + static int -check_gpt(struct biosdisk *d, daddr_t sector) +check_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t sector) { struct gpt_hdr gpth; const struct gpt_ent *ep; const struct uuid *u; @@ -295,9 +386,9 @@ if (gpth.hdr_crc_self != crc) { return -1; } - if (gpth.hdr_lba_self != sector) + if (gpth.hdr_lba_self + rf_offset != sector) return -1; #ifdef _STANDALONE bi_wedge.matchblk = sector; @@ -307,9 +398,9 @@ #endif sectors = sizeof(d->buf)/d->ll.secsize; /* sectors per buffer */ entries = sizeof(d->buf)/gpth.hdr_entsz; /* entries per buffer */ - entblk = gpth.hdr_lba_table; + entblk = gpth.hdr_lba_table + rf_offset; crc = crc32(0, NULL, 0); j = 0; ep = (const struct gpt_ent *)d->buf; @@ -343,16 +434,23 @@ else if (guid_is_equal(u, &GET_nbsd_cgd)) d->part[j].fstype = FS_CGD; else d->part[j].fstype = FS_OTHER; -#ifdef EFIBOOT +#ifndef NO_GPT for (int k = 0; k < __arraycount(gpt_parts); k++) { if (guid_is_equal(u, gpt_parts[k].guid)) d->part[j].guid = &gpt_parts[k]; } d->part[j].attr = ep[i].ent_attr; + + d->part[j].part_name = + alloc(BIOSDISK_PART_NAME_LEN); + part_name_utf8(ep[i].ent_name, + sizeof(ep[i].ent_name), + d->part[j].part_name, + BIOSDISK_PART_NAME_LEN); #endif j++; } } @@ -369,9 +467,9 @@ return 0; } static int -read_gpt(struct biosdisk *d) +read_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t rf_size) { struct biosdisk_extinfo ed; daddr_t gptsector[2]; int i, error; @@ -379,25 +477,32 @@ if (d->ll.type != BIOSDISK_TYPE_HD) /* No GPT on floppy and CD */ return -1; - gptsector[0] = GPT_HDR_BLKNO; - if (set_geometry(&d->ll, &ed) == 0 && d->ll.flags & BIOSDISK_INT13EXT) { - gptsector[1] = ed.totsec - 1; - /* Sanity check values returned from BIOS */ - if (ed.sbytes >= 512 && (ed.sbytes & (ed.sbytes - 1)) == 0) - d->ll.secsize = ed.sbytes; + if (rf_offset && rf_size) { + gptsector[0] = rf_offset + GPT_HDR_BLKNO; + gptsector[1] = rf_offset + rf_size - 1; } else { + gptsector[0] = GPT_HDR_BLKNO; + if (set_geometry(&d->ll, &ed) == 0 && + d->ll.flags & BIOSDISK_INT13EXT) { + gptsector[1] = ed.totsec - 1; + /* Sanity check values returned from BIOS */ + if (ed.sbytes >= 512 && + (ed.sbytes & (ed.sbytes - 1)) == 0) + d->ll.secsize = ed.sbytes; + } else { #ifdef DISK_DEBUG - printf("Unable to determine extended disk geometry - " - "using CHS\n"); + printf("Unable to determine extended disk geometry - " + "using CHS\n"); #endif - /* at least try some other reasonable values then */ - gptsector[1] = d->ll.chs_sectors - 1; + /* at least try some other reasonable values then */ + gptsector[1] = d->ll.chs_sectors - 1; + } } for (i = 0; i < __arraycount(gptsector); i++) { - error = check_gpt(d, gptsector[i]); + error = check_gpt(d, rf_offset, gptsector[i]); if (error == 0) break; } @@ -545,9 +650,9 @@ } #endif static int -read_label(struct biosdisk *d) +read_label(struct biosdisk *d, daddr_t offset) { struct disklabel dflt_lbl; struct mbr_partition mbr[MBR_PART_COUNT]; struct partition *p; @@ -572,13 +677,13 @@ /* * find NetBSD Partition in DOS partition table * XXX check magic??? */ - ext_base = 0; - next_ext = 0; + ext_base = offset; + next_ext = offset; for (;;) { this_ext = ext_base + next_ext; - next_ext = 0; + next_ext = offset; if (readsects(&d->ll, this_ext, 1, d->buf, 0)) { #ifdef DISK_DEBUG printf("error reading MBR sector %u\n", this_ext); #endif @@ -606,16 +711,16 @@ if (error >= 0) return error; } if (MBR_IS_EXTENDED(typ)) { - next_ext = mbr[i].mbrp_start; + next_ext = mbr[i].mbrp_start + offset; continue; } #ifdef COMPAT_386BSD_MBRPART - if (this_ext == 0 && typ == MBR_PTYPE_386BSD) + if (this_ext == offset && typ == MBR_PTYPE_386BSD) sector_386bsd = sector; #endif - if (this_ext != 0) { + if (this_ext != offset) { if (dflt_lbl.d_npartitions >= MAXPARTITIONS) continue; p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++]; } else @@ -623,17 +728,17 @@ p->p_offset = sector; p->p_size = mbr[i].mbrp_size; p->p_fstype = xlat_mbr_fstype(typ); } - if (next_ext == 0) + if (next_ext == offset) break; - if (ext_base == 0) { + if (ext_base == offset) { ext_base = next_ext; - next_ext = 0; + next_ext = offset; } } - sector = 0; + sector = offset; #ifdef COMPAT_386BSD_MBRPART if (sector_386bsd != -1) { printf("old BSD partition ID!\n"); sector = sector_386bsd; @@ -670,33 +775,76 @@ #endif /* NO_DISKLABEL */ #if !defined(NO_DISKLABEL) || !defined(NO_GPT) static int -read_partitions(struct biosdisk *d) +read_partitions(struct biosdisk *d, daddr_t offset, daddr_t size) { int error; error = -1; #ifndef NO_GPT - error = read_gpt(d); + error = read_gpt(d, offset, size); if (error == 0) return 0; #endif #ifndef NO_DISKLABEL - error = read_label(d); + error = read_label(d, offset); #endif return error; } #endif +#ifndef NO_RAIDFRAME +static void +raidframe_probe(struct raidframe *raidframe, int *raidframe_count, + struct biosdisk *d, int part) +{ + int i = *raidframe_count; + struct RF_ComponentLabel_s label; + daddr_t offset; + + if (i + 1 > RAIDFRAME_NDEV) + return; + + offset = d->part[part].offset; + if ((biosdisk_read_raidframe(d->ll.dev, offset, &label)) != 0) + return; + + if (label.version != RF_COMPONENT_LABEL_VERSION) + printf("Unexpected raidframe label version\n"); + + raidframe[i].last_unit = label.last_unit; + raidframe[i].serial = label.serial_number; + raidframe[i].biosdev = d->ll.dev; + raidframe[i].parent_part = part; +#ifndef NO_GPT + if (d->part[part].part_name) + strlcpy(raidframe[i].parent_name, + d->part[part].part_name, MAXDEVNAME); + else + raidframe[i].parent_name[0] = '\0'; +#endif + raidframe[i].offset = offset; + raidframe[i].size = label.__numBlocks; + + (*raidframe_count)++; + + return; +} +#endif + void biosdisk_probe(void) { - struct biosdisk d; + struct biosdisk *d; struct biosdisk_extinfo ed; +#ifndef NO_RAIDFRAME + struct raidframe raidframe[RAIDFRAME_NDEV]; + int raidframe_count = 0; +#endif uint64_t size; int first; int i; #if !defined(NO_DISKLABEL) || !defined(NO_GPT) @@ -704,28 +852,33 @@ #endif for (i = 0; i < MAX_BIOSDISKS + 2; i++) { first = 1; - memset(&d, 0, sizeof(d)); + d = alloc(sizeof(*d)); + if (d == NULL) { + printf("Out of memory\n"); + return; + } + memset(d, 0, sizeof(d)); memset(&ed, 0, sizeof(ed)); if (i >= MAX_BIOSDISKS) - d.ll.dev = 0x00 + i - MAX_BIOSDISKS; /* fd */ + d->ll.dev = 0x00 + i - MAX_BIOSDISKS; /* fd */ else - d.ll.dev = 0x80 + i; /* hd/cd */ - if (set_geometry(&d.ll, &ed)) - continue; + d->ll.dev = 0x80 + i; /* hd/cd */ + if (set_geometry(&d->ll, &ed)) + goto next_disk; printf("disk "); - switch (d.ll.type) { + switch (d->ll.type) { case BIOSDISK_TYPE_CD: printf("cd0\n cd0a\n"); break; case BIOSDISK_TYPE_FD: - printf("fd%d\n", d.ll.dev & 0x7f); - printf(" fd%da\n", d.ll.dev & 0x7f); + printf("fd%d\n", d->ll.dev & 0x7f); + printf(" fd%da\n", d->ll.dev & 0x7f); break; case BIOSDISK_TYPE_HD: - printf("hd%d", d.ll.dev & 0x7f); - if (d.ll.flags & BIOSDISK_INT13EXT) { + printf("hd%d", d->ll.dev & 0x7f); + if (d->ll.flags & BIOSDISK_INT13EXT) { printf(" size "); size = ed.totsec * ed.sbytes; if (size >= (10ULL * 1024 * 1024 * 1024)) printf("%"PRIu64" GB", @@ -737,40 +890,134 @@ printf("\n"); break; } #if !defined(NO_DISKLABEL) || !defined(NO_GPT) - if (d.ll.type != BIOSDISK_TYPE_HD) - continue; + if (d->ll.type != BIOSDISK_TYPE_HD) + goto next_disk; - if (read_partitions(&d) != 0) - continue; + if (read_partitions(d, 0, 0) != 0) + goto next_disk; for (part = 0; part < BIOSDISKNPART; part++) { - if (d.part[part].size == 0) + if (d->part[part].size == 0) continue; - if (d.part[part].fstype == FS_UNUSED) + if (d->part[part].fstype == FS_UNUSED) continue; +#ifndef NO_RAIDFRAME + if (d->part[part].fstype == FS_RAID) + raidframe_probe(raidframe, + &raidframe_count, d, part); +#endif if (first) { printf(" "); first = 0; } - printf(" hd%d%c(", d.ll.dev & 0x7f, part + 'a'); -#ifdef EFIBOOT - if (d.part[part].guid != NULL) - printf("%s", d.part[part].guid->name); +#ifndef NO_GPT + if (d->part[part].part_name != NULL) + printf(" NAME=%s(", d->part[part].part_name); else #endif - if (d.part[part].fstype < FSMAXTYPES) + printf(" hd%d%c(", d->ll.dev & 0x7f, part + 'a'); + +#ifndef NO_GPT + if (d->part[part].guid != NULL) + printf("%s", d->part[part].guid->name); + else +#endif + + if (d->part[part].fstype < FSMAXTYPES) printf("%s", - fstypenames[d.part[part].fstype]); + fstypenames[d->part[part].fstype]); else - printf("%d", d.part[part].fstype); + printf("%d", d->part[part].fstype); printf(")"); } #endif if (first == 0) printf("\n"); + +next_disk: + dealloc_biosdisk(d); } + +#ifndef NO_RAIDFRAME + for (i = 0; i < raidframe_count; i++) { + size_t secsize; + + if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { + printf("Out of memory\n"); + return; + } + + secsize = d->ll.secsize; + + printf("raidframe raid%d serial %d in ", + raidframe[i].last_unit, raidframe[i].serial); +#ifndef NO_GPT + if (raidframe[i].parent_name[0]) + printf("NAME=%s size ", raidframe[i].parent_name); + else +#endif + printf("hd%d%c size ", d->ll.dev & 0x7f, + raidframe[i].parent_part + 'a'); + if (raidframe[i].size >= (10ULL * 1024 * 1024 * 1024 / secsize)) + printf("%"PRIu64" GB", + raidframe[i].size / (1024 * 1024 * 1024 / secsize)); + else + printf("%"PRIu64" MB", + raidframe[i].size / (1024 * 1024 / secsize)); + printf("\n"); + + if (read_partitions(d, + raidframe[i].offset + RF_PROTECTED_SECTORS, + raidframe[i].size) != 0) + goto next_raidrame; + + first = 1; + for (part = 0; part < BIOSDISKNPART; part++) { +#ifndef NO_GPT + bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME; +#else + bool bootme = 0; +#endif + + if (d->part[part].size == 0) + continue; + if (d->part[part].fstype == FS_UNUSED) + continue; + if (d->part[part].fstype == FS_RAID) + continue; + if (first) { + printf(" "); + first = 0; + } +#ifndef NO_GPT + if (d->part[part].part_name != NULL) + printf(" NAME=%s(", d->part[part].part_name); + else +#endif + printf(" raid%d%c(", raidframe[i].last_unit, + part + 'a'); +#ifndef NO_GPT + if (d->part[part].guid != NULL) + printf("%s", d->part[part].guid->name); + else +#endif + if (d->part[part].fstype < FSMAXTYPES) + printf("%s", + fstypenames[d->part[part].fstype]); + else + printf("%d", d->part[part].fstype); + printf("%s)", bootme ? ", bootme" : ""); + } + +next_raidrame: + if (first == 0) + printf("\n"); + + dealloc_biosdisk(d); + } +#endif } /* Determine likely partition for possible sector number of dos * partition. @@ -783,9 +1030,9 @@ return 0; #else struct biosdisk *d; int partition = 0; -#ifdef EFIBOOT +#ifndef NO_GPT int candidate = 0; #endif #ifdef DISK_DEBUG @@ -796,13 +1043,13 @@ d = alloc_biosdisk(biosdev); if (d == NULL) return 0; - if (read_partitions(d) == 0) { + if (read_partitions(d, 0, 0) == 0) { for (partition = (BIOSDISKNPART-1); --partition;) { if (d->part[partition].fstype == FS_UNUSED) continue; -#ifdef EFIBOOT +#ifndef NO_GPT switch (d->part[partition].fstype) { case FS_BSDFFS: case FS_BSDLFS: case FS_RAID: @@ -823,23 +1070,23 @@ if (d->part[partition].offset == sector) break; #endif } -#ifdef EFIBOOT +#ifndef NO_GPT found: if (partition == 0 && candidate != 0) partition = candidate; #endif } - dealloc(d, sizeof(*d)); + dealloc_biosdisk(d); return partition; #endif /* NO_DISKLABEL && NO_GPT */ } int -biosdisk_readpartition(int biosdev, struct biosdisk_partition **partpp, - int *rnum) +biosdisk_readpartition(int biosdev, daddr_t offset, daddr_t size, + struct biosdisk_partition **partpp, int *rnum) { #if defined(NO_DISKLABEL) && defined(NO_GPT) return ENOTSUP; #else @@ -851,28 +1098,71 @@ d = alloc_biosdisk(biosdev); if (d == NULL) return ENOMEM; - if (read_partitions(d)) { + if (read_partitions(d, offset, size)) { rv = EINVAL; goto out; } - part = alloc(sizeof(d->part)); + part = copy_biosdisk_part(d); if (part == NULL) { rv = ENOMEM; goto out; } - memcpy(part, d->part, sizeof(d->part)); *partpp = part; *rnum = (int)__arraycount(d->part); rv = 0; out: - dealloc(d, sizeof(*d)); + dealloc_biosdisk(d); + return rv; +#endif /* NO_DISKLABEL && NO_GPT */ +} + +#ifndef NO_RAIDFRAME +int +biosdisk_read_raidframe(int biosdev, daddr_t offset, + struct RF_ComponentLabel_s *label) +{ +#if defined(NO_DISKLABEL) && defined(NO_GPT) + return ENOTSUP; +#else + struct biosdisk *d; + struct biosdisk_extinfo ed; + daddr_t size; + int rv = -1; + + /* Look for netbsd partition that is the dos boot one */ + d = alloc_biosdisk(biosdev); + if (d == NULL) + goto out; + + if (d->ll.type != BIOSDISK_TYPE_HD) + /* No raidframe on floppy and CD */ + goto out; + + if (set_geometry(&d->ll, &ed) != 0) + goto out; + + /* Sanity check values returned from BIOS */ + if (ed.sbytes >= 512 && + (ed.sbytes & (ed.sbytes - 1)) == 0) + d->ll.secsize = ed.sbytes; + + offset += (RF_COMPONENT_INFO_OFFSET / d->ll.secsize); + size = roundup(sizeof(*label), d->ll.secsize) / d->ll.secsize; + if (readsects(&d->ll, offset, size, d->buf, 0)) + goto out; + memcpy(label, d->buf, sizeof(*label)); + rv = 0; +out: + if (d != NULL) + dealloc_biosdisk(d); return rv; #endif /* NO_DISKLABEL && NO_GPT */ } +#endif /* NO_RAIDFRAME */ #ifdef _STANDALONE static void add_biosdisk_bootinfo(void) @@ -885,8 +1175,41 @@ return; } #endif +#ifndef NO_GPT +static daddr_t +raidframe_part_offset(struct biosdisk *d, int part) +{ + struct biosdisk raidframe; + daddr_t rf_offset; + daddr_t rf_size; + int i, candidate; + + memset(&raidframe, 0, sizeof(raidframe)); + raidframe.ll = d->ll; + + rf_offset = d->part[part].offset + RF_PROTECTED_SECTORS; + rf_size = d->part[part].size; + if (read_gpt(&raidframe, rf_offset, rf_size) != 0) + return RF_PROTECTED_SECTORS; + + candidate = 0; + for (i = 0; i < BIOSDISKNPART; i++) { + if (raidframe.part[i].size == 0) + continue; + if (raidframe.part[i].fstype == FS_UNUSED) + continue; +#ifndef NO_GPT + if (raidframe.part[i].attr & GPT_ENT_ATTR_BOOTME) + candidate = i; +#endif + } + + return RF_PROTECTED_SECTORS + raidframe.part[candidate].offset; +} +#endif + int biosdisk_open(struct open_file *f, ...) /* struct open_file *f, int biosdev, int partition */ { @@ -914,9 +1237,9 @@ bi_wedge.matchblk = -1; #endif #if !defined(NO_DISKLABEL) || !defined(NO_GPT) - error = read_partitions(d); + error = read_partitions(d, 0, 0); if (error == -1) { error = 0; goto nolabel; } @@ -934,9 +1257,13 @@ d->boff = d->part[partition].offset; if (d->part[partition].fstype == FS_RAID) +#ifndef NO_GPT + d->boff += raidframe_part_offset(d, partition); +#else d->boff += RF_PROTECTED_SECTORS; +#endif #ifdef _STANDALONE bi_wedge.startblk = d->part[partition].offset; bi_wedge.nblks = d->part[partition].size; @@ -955,12 +1282,312 @@ f->f_devdata = d; out: va_end(ap); if (error) - dealloc(d, sizeof(*d)); + dealloc_biosdisk(d); + return error; +} + +#ifndef NO_GPT +static int +biosdisk_find_name(const char *fname, int *biosdev, + daddr_t *offset, daddr_t *size) +{ + struct biosdisk *d; + char name[MAXDEVNAME + 1]; + char *sep; +#ifndef NO_RAIDFRAME + struct raidframe raidframe[RAIDFRAME_NDEV]; + int raidframe_count = 0; +#endif + int i; + int part; + int ret = -1; + + /* Strip leadinf NAME= and cut after the coloon included */ + strlcpy(name, fname + 5, MAXDEVNAME); + sep = strchr(name, ':'); + if (sep) + *sep = '\0'; + + for (i = 0; i < MAX_BIOSDISKS; i++) { + d = alloc(sizeof(*d)); + if (d == NULL) { + printf("Out of memory\n"); + goto out; + } + + memset(d, 0, sizeof(*d)); + d->ll.dev = 0x80 + i; /* hd/cd */ + if (set_geometry(&d->ll, NULL)) + goto next_disk; + + if (d->ll.type != BIOSDISK_TYPE_HD) + goto next_disk; + + if (read_partitions(d, 0, 0) != 0) + goto next_disk; + + for (part = 0; part < BIOSDISKNPART; part++) { + if (d->part[part].size == 0) + continue; + if (d->part[part].fstype == FS_UNUSED) + continue; +#ifndef NO_RAIDFRAME + if (d->part[part].fstype == FS_RAID) { + raidframe_probe(raidframe, + &raidframe_count, d, part); + /* + * Do not match RAID partition for a name, + * we want to report an inner partition. + */ + continue; + } +#endif + if (d->part[part].part_name != NULL && + strcmp(d->part[part].part_name, name) == 0) { + *biosdev = d->ll.dev; + *offset = d->part[part].offset; + *size = d->part[part].size; + ret = 0; + goto out; + } + + } +next_disk: + dealloc_biosdisk(d); + d = NULL; + } + +#ifndef NO_RAIDFRAME + for (i = 0; i < raidframe_count; i++) { + int candidate = -1; + + if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { + printf("Out of memory\n"); + goto out; + } + + if (read_partitions(d, + raidframe[i].offset + RF_PROTECTED_SECTORS, + raidframe[i].size) != 0) + goto next_raidframe; + + for (part = 0; part < BIOSDISKNPART; part++) { + bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME; + if (d->part[part].size == 0) + continue; + if (d->part[part].fstype == FS_UNUSED) + continue; + if (d->part[part].part_name == NULL) + continue; + if (strcmp(d->part[part].part_name, name) == 0) { + *biosdev = raidframe[i].biosdev; + *offset = raidframe[i].offset + + RF_PROTECTED_SECTORS + + d->part[part].offset; + *size = d->part[part].size; + ret = 0; + goto out; + } + if (strcmp(raidframe[i].parent_name, name) == 0) { + if (candidate == -1 || bootme) + candidate = part; + continue; + } + } + + if (candidate != -1) { + *biosdev = raidframe[i].biosdev; + *offset = raidframe[i].offset + + RF_PROTECTED_SECTORS + + d->part[candidate].offset; + *size = d->part[candidate].size; + ret = 0; + goto out; + } + +next_raidframe: + dealloc_biosdisk(d); + d = NULL; + } +#endif + +out: + if (d != NULL) + dealloc_biosdisk(d); + + return ret; +} +#endif + +#ifndef NO_RAIDFRAME +static int +biosdisk_find_raid(const char *name, int *biosdev, + daddr_t *offset, daddr_t *size) +{ + struct biosdisk *d = NULL; + struct raidframe raidframe[RAIDFRAME_NDEV]; + int raidframe_count = 0; + int i; + int target_unit = 0; + int target_part; + int part; + int ret = -1; + + if (strstr(name, "raid") != name) + goto out; + +#define isnum(c) ((c) >= '0' && (c) <= '9') + i = 4; /* skip leading "raid" */ + if (!isnum(name[i])) + goto out; + do { + target_unit *= 10; + target_unit += name[i++] - '0'; + } while (isnum(name[i])); + +#define isvalidpart(c) ((c) >= 'a' && (c) <= 'z') + + if (!isvalidpart(name[i])) + goto out; + target_part = name[i] - 'a'; + + for (i = 0; i < MAX_BIOSDISKS; i++) { + d = alloc(sizeof(*d)); + if (d == NULL) { + printf("Out of memory\n"); + goto out; + } + + memset(d, 0, sizeof(*d)); + d->ll.dev = 0x80 + i; /* hd/cd */ + if (set_geometry(&d->ll, NULL)) + goto next_disk; + + if (d->ll.type != BIOSDISK_TYPE_HD) + goto next_disk; + + if (read_partitions(d, 0, 0) != 0) + goto next_disk; + + for (part = 0; part < BIOSDISKNPART; part++) { + if (d->part[part].size == 0) + continue; + if (d->part[part].fstype != FS_RAID) + continue; + raidframe_probe(raidframe, + &raidframe_count, d, part); + + } +next_disk: + dealloc_biosdisk(d); + d = NULL; + } + + for (i = 0; i < raidframe_count; i++) { + if (raidframe[i].last_unit != target_unit) + continue; + + if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { + printf("Out of memory\n"); + goto out; + } + + if (read_partitions(d, + raidframe[i].offset + RF_PROTECTED_SECTORS, + raidframe[i].size) != 0) + goto next_raidframe; + + for (part = 0; part < BIOSDISKNPART; part++) { + if (d->part[part].size == 0) + continue; + if (d->part[part].fstype == FS_UNUSED) + continue; + if (part == target_part) { + *biosdev = raidframe[i].biosdev; + *offset = raidframe[i].offset + + RF_PROTECTED_SECTORS + + d->part[part].offset; + *size = d->part[part].size; + ret = 0; + goto out; + } + } +next_raidframe: + dealloc_biosdisk(d); + d = NULL; + } +out: + if (d != NULL) + dealloc_biosdisk(d); + + return ret; +} +#endif + +int +biosdisk_open_name(struct open_file *f, const char *name) +{ +#if defined(NO_GPT) && defined(NO_RAIDFRAME) + return ENXIO; +#else + struct biosdisk *d = NULL; + int biosdev; + daddr_t offset; + daddr_t size; + int error = -1; + +#ifndef NO_GPT + if (strstr(name, "NAME=") == name) + error = biosdisk_find_name(name, &biosdev, &offset, &size); +#endif +#ifndef NO_RAIDFRAME + if (strstr(name, "raid") == name) + error = biosdisk_find_raid(name, &biosdev, &offset, &size); +#endif + + if (error != 0) { + printf("partition %s not found\n", name); + error = ENXIO; + goto out; + } + + d = alloc_biosdisk(biosdev); + if (d == NULL) { + error = ENXIO; + goto out; + } + +#ifdef _STANDALONE + bi_disk.biosdev = d->ll.dev; + bi_disk.partition = 0; + bi_disk.labelsector = -1; + + bi_wedge.biosdev = d->ll.dev; + bi_wedge.matchblk = offset; + bi_wedge.matchnblks = 1; +#endif + + d->boff = offset; + +#ifdef _STANDALONE + bi_wedge.startblk = offset; + bi_wedge.nblks = size; + + add_biosdisk_bootinfo(); +#endif + + f->f_devdata = d; +out: + if (error && d != NULL) + dealloc_biosdisk(d); return error; +#endif } + + #ifndef LIBSA_NO_FS_CLOSE int biosdisk_close(struct open_file *f) { @@ -969,9 +1596,9 @@ /* let the floppy drive go off */ if (d->ll.type == BIOSDISK_TYPE_FD) wait_sec(3); /* 2s is enough on all PCs I found */ - dealloc(d, sizeof(*d)); + dealloc_biosdisk(d); f->f_devdata = NULL; return 0; } #endif Index: sys/arch/i386/stand/lib/biosdisk.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/stand/lib/biosdisk.h,v retrieving revision 1.10 diff -U4 -r1.10 biosdisk.h --- sys/arch/i386/stand/lib/biosdisk.h 2 Apr 2018 09:44:18 -0000 1.10 +++ sys/arch/i386/stand/lib/biosdisk.h 10 Aug 2019 01:47:34 -0000 @@ -24,27 +24,35 @@ * (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 BIOSDISK_PART_NAME_LEN 36 + struct biosdisk_partition { daddr_t offset; daddr_t size; int fstype; -#ifdef EFIBOOT +#ifndef NO_GPT const struct gpt_part { const struct uuid *guid; const char *name; } *guid; uint64_t attr; + char *part_name; /* maximum BIOSDISK_PART_NAME_LEN */ #endif }; int biosdisk_strategy(void *, int, daddr_t, size_t, void *, size_t *); int biosdisk_open(struct open_file *, ...); +int biosdisk_open_name(struct open_file *, const char *); int biosdisk_close(struct open_file *); int biosdisk_ioctl(struct open_file *, u_long, void *); int biosdisk_findpartition(int, daddr_t); -int biosdisk_readpartition(int, struct biosdisk_partition **, int *); +int biosdisk_readpartition(int, daddr_t, daddr_t, + struct biosdisk_partition **, int *); + +struct RF_ComponentLabel_s; +int biosdisk_read_raidframe(int, daddr_t, struct RF_ComponentLabel_s *); #if !defined(NO_GPT) struct uuid; bool guid_is_nil(const struct uuid *);