Date: Sun, 5 Aug 2012 14:06:06 +0100 From: Doug Rabson <dfr@rabson.org> To: "Andrey V. Elsukov" <ae@FreeBSD.org> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r239058 - in head/sys/boot: common userboot userboot/test userboot/userboot Message-ID: <050317CF-D855-4DA4-B15E-E032905260D5@rabson.org> In-Reply-To: <201208051215.q75CFFPO081805@svn.freebsd.org> References: <201208051215.q75CFFPO081805@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
If you change the loader callbacks structure, you need to change the = version number to avoid unexpected results for mismatched combinations = of application and userboot.so. On 5 Aug 2012, at 13:15, Andrey V. Elsukov wrote: > Author: ae > Date: Sun Aug 5 12:15:15 2012 > New Revision: 239058 > URL: http://svn.freebsd.org/changeset/base/239058 >=20 > Log: > Introduce new API to work with disks from the loader's drivers. > It uses new API from the part.c to work with partition tables. >=20 > Update userboot's disk driver to use new API. Note that struct > loader_callbacks_v1 has changed. >=20 > Modified: > head/sys/boot/common/Makefile.inc > head/sys/boot/common/disk.c > head/sys/boot/common/disk.h > head/sys/boot/userboot/test/test.c > head/sys/boot/userboot/userboot.h > head/sys/boot/userboot/userboot/Makefile > head/sys/boot/userboot/userboot/devicename.c > head/sys/boot/userboot/userboot/userboot_disk.c >=20 > Modified: head/sys/boot/common/Makefile.inc > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- head/sys/boot/common/Makefile.inc Sun Aug 5 11:59:46 2012 = (r239057) > +++ head/sys/boot/common/Makefile.inc Sun Aug 5 12:15:15 2012 = (r239058) > @@ -1,6 +1,6 @@ > # $FreeBSD$ >=20 > -SRCS+=3D boot.c commands.c console.c devopen.c disk.c interp.c=20 > +SRCS+=3D boot.c commands.c console.c devopen.c interp.c=20 > SRCS+=3D interp_backslash.c interp_parse.c ls.c misc.c=20 > SRCS+=3D module.c panic.c >=20 > @@ -24,6 +24,18 @@ SRCS+=3D load_elf64.c reloc_elf64.c > SRCS+=3D dev_net.c > .endif >=20 > +.if !defined(LOADER_NO_DISK_SUPPORT) > +SRCS+=3D disk.c part.c > +CFLAGS+=3D -DLOADER_DISK_SUPPORT > +.if !defined(LOADER_NO_GPT_SUPPORT) > +SRCS+=3D crc32.c > +CFLAGS+=3D -DLOADER_GPT_SUPPORT > +.endif > +.if !defined(LOADER_NO_MBR_SUPPORT) > +CFLAGS+=3D -DLOADER_MBR_SUPPORT > +.endif > +.endif > + > .if defined(HAVE_BCACHE) > SRCS+=3D bcache.c > .endif >=20 > Modified: head/sys/boot/common/disk.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- head/sys/boot/common/disk.c Sun Aug 5 11:59:46 2012 = (r239057) > +++ head/sys/boot/common/disk.c Sun Aug 5 12:15:15 2012 = (r239058) > @@ -1,5 +1,6 @@ > /*- > * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> > + * Copyright (c) 2012 Andrey V. Elsukov <ae@FreeBSD.org> > * All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > @@ -27,26 +28,11 @@ > #include <sys/cdefs.h> > __FBSDID("$FreeBSD$"); >=20 > -/* > - * MBR/GPT partitioned disk device handling. > - * > - * Ideas and algorithms from: > - * > - * - NetBSD libi386/biosdisk.c > - * - FreeBSD biosboot/disk.c > - * > - */ > - > +#include <sys/disk.h> > #include <stand.h> > - > -#include <sys/diskmbr.h> > -#include <sys/disklabel.h> > -#include <sys/gpt.h> > - > #include <stdarg.h> > -#include <uuid.h> > - > #include <bootstrap.h> > +#include <part.h> >=20 > #include "disk.h" >=20 > @@ -56,53 +42,26 @@ __FBSDID("$FreeBSD$"); > # define DEBUG(fmt, args...) > #endif >=20 > -/* > - * Search for a slice with the following preferences: > - * > - * 1: Active FreeBSD slice > - * 2: Non-active FreeBSD slice > - * 3: Active Linux slice > - * 4: non-active Linux slice > - * 5: Active FAT/FAT32 slice > - * 6: non-active FAT/FAT32 slice > - */ > -#define PREF_RAWDISK 0 > -#define PREF_FBSD_ACT 1 > -#define PREF_FBSD 2 > -#define PREF_LINUX_ACT 3 > -#define PREF_LINUX 4 > -#define PREF_DOS_ACT 5 > -#define PREF_DOS 6 > -#define PREF_NONE 7 > - > -#ifdef LOADER_GPT_SUPPORT > - > -struct gpt_part { > - int gp_index; > - uuid_t gp_type; > - uint64_t gp_start; > - uint64_t gp_end; > +struct open_disk { > + struct ptable *table; > + off_t mediasize; > + u_int sectorsize; > }; >=20 > -static uuid_t efi =3D GPT_ENT_TYPE_EFI; > -static uuid_t freebsd_boot =3D GPT_ENT_TYPE_FREEBSD_BOOT; > -static uuid_t freebsd_ufs =3D GPT_ENT_TYPE_FREEBSD_UFS; > -static uuid_t freebsd_swap =3D GPT_ENT_TYPE_FREEBSD_SWAP; > -static uuid_t freebsd_zfs =3D GPT_ENT_TYPE_FREEBSD_ZFS; > -static uuid_t ms_basic_data =3D GPT_ENT_TYPE_MS_BASIC_DATA; > - > -#endif > - > -#if defined(LOADER_GPT_SUPPORT) || defined(LOADER_MBR_SUPPORT) > +struct print_args { > + struct disk_devdesc *dev; > + const char *prefix; > + int verbose; > +}; >=20 > -/* Given a size in 512 byte sectors, convert it to a human-readable = number. */ > +/* Convert size to a human-readable number. */ > static char * > -display_size(uint64_t size) > +display_size(uint64_t size, u_int sectorsize) > { > static char buf[80]; > char unit; >=20 > - size /=3D 2; > + size =3D size * sectorsize / 1024; > unit =3D 'K'; > if (size >=3D 10485760000LL) { > size /=3D 1073741824; > @@ -114,687 +73,230 @@ display_size(uint64_t size) > size /=3D 1024; > unit =3D 'M'; > } > - sprintf(buf, "%.6ld%cB", (long)size, unit); > + sprintf(buf, "%ld%cB", (long)size, unit); > return (buf); > } >=20 > -#endif > - > -#ifdef LOADER_MBR_SUPPORT > - > -static void > -disk_checkextended(struct disk_devdesc *dev, > - struct dos_partition *slicetab, int slicenum, int *nslicesp) > -{ > - uint8_t buf[DISK_SECSIZE]; > - struct dos_partition *dp; > - uint32_t base; > - int rc, i, start, end; > - > - dp =3D &slicetab[slicenum]; > - start =3D *nslicesp; > - > - if (dp->dp_size =3D=3D 0) > - goto done; > - if (dp->dp_typ !=3D DOSPTYP_EXT) > - goto done; > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, dp->dp_start, = DISK_SECSIZE, > - (char *) buf, NULL); > - if (rc) > - goto done; > - if (buf[0x1fe] !=3D 0x55 || buf[0x1ff] !=3D 0xaa) { > - DEBUG("no magic in extended table"); > - goto done; > - } > - base =3D dp->dp_start; > - dp =3D (struct dos_partition *) &buf[DOSPARTOFF]; > - for (i =3D 0; i < NDOSPART; i++, dp++) { > - if (dp->dp_size =3D=3D 0) > - continue; > - if (*nslicesp =3D=3D NEXTDOSPART) > - goto done; > - dp->dp_start +=3D base; > - bcopy(dp, &slicetab[*nslicesp], sizeof(*dp)); > - (*nslicesp)++; > - } > - end =3D *nslicesp; > - > - /* > - * now, recursively check the slices we just added > - */ > - for (i =3D start; i < end; i++) > - disk_checkextended(dev, slicetab, i, nslicesp); > -done: > - return; > -} > - > -static int > -disk_readslicetab(struct disk_devdesc *dev, > - struct dos_partition **slicetabp, int *nslicesp) > -{ > - struct dos_partition *slicetab =3D NULL; > - int nslices, i; > - int rc; > - uint8_t buf[DISK_SECSIZE]; > - > - /* > - * Find the slice in the DOS slice table. > - */ > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, 0, DISK_SECSIZE, > - (char *) buf, NULL); > - if (rc) { > - DEBUG("error reading MBR"); > - return (rc); > - } > - > - /* > - * Check the slice table magic. > - */ > - if (buf[0x1fe] !=3D 0x55 || buf[0x1ff] !=3D 0xaa) { > - DEBUG("no slice table/MBR (no magic)"); > - return (rc); > - } > - > - /* > - * copy the partition table, then pick up any extended = partitions. > - */ > - slicetab =3D malloc(NEXTDOSPART * sizeof(struct dos_partition)); > - bcopy(buf + DOSPARTOFF, slicetab, > - sizeof(struct dos_partition) * NDOSPART); > - nslices =3D NDOSPART; /* extended slices start here */ > - for (i =3D 0; i < NDOSPART; i++) > - disk_checkextended(dev, slicetab, i, &nslices); > - > - *slicetabp =3D slicetab; > - *nslicesp =3D nslices; > - return (0); > -} > - > -/* > - * Search for the best MBR slice (typically the first FreeBSD slice). > - */ > -static int > -disk_bestslice(struct dos_partition *slicetab, int nslices) > -{ > - struct dos_partition *dp; > - int pref, preflevel; > - int i, prefslice; > - > - prefslice =3D 0; > - preflevel =3D PREF_NONE; > - > - dp =3D &slicetab[0]; > - for (i =3D 0; i < nslices; i++, dp++) { > - switch (dp->dp_typ) { > - case DOSPTYP_386BSD: /* FreeBSD */ > - pref =3D dp->dp_flag & 0x80 ? PREF_FBSD_ACT : = PREF_FBSD; > - break; > - > - case DOSPTYP_LINUX: > - pref =3D dp->dp_flag & 0x80 ? PREF_LINUX_ACT : = PREF_LINUX; > - break; > - > - case 0x01: /* DOS/Windows */ > - case 0x04: > - case 0x06: > - case 0x0b: > - case 0x0c: > - case 0x0e: > - pref =3D dp->dp_flag & 0x80 ? PREF_DOS_ACT : = PREF_DOS; > - break; > - > - default: > - pref =3D PREF_NONE; > - } > - if (pref < preflevel) { > - preflevel =3D pref; > - prefslice =3D i + 1; > - } > - } > - return (prefslice); > -} > - > static int > -disk_openmbr(struct disk_devdesc *dev) > -{ > - struct dos_partition *slicetab =3D NULL, *dptr; > - int nslices, sector, slice; > - int rc; > - uint8_t buf[DISK_SECSIZE]; > - struct disklabel *lp; > - > - /* > - * Following calculations attempt to determine the correct value > - * for dev->d_offset by looking for the slice and partition = specified, > - * or searching for reasonable defaults. > - */ > - rc =3D disk_readslicetab(dev, &slicetab, &nslices); > - if (rc) > - return (rc); > - > - /* > - * if a slice number was supplied but not found, this is an = error. > - */ > - if (dev->d_slice > 0) { > - slice =3D dev->d_slice - 1; > - if (slice >=3D nslices) { > - DEBUG("slice %d not found", slice); > - rc =3D EPART; > - goto out; > - } > - } > - > - /* > - * Check for the historically bogus MBR found on true dedicated = disks > - */ > - if (slicetab[3].dp_typ =3D=3D DOSPTYP_386BSD && > - slicetab[3].dp_start =3D=3D 0 && slicetab[3].dp_size =3D=3D = 50000) { > - sector =3D 0; > - goto unsliced; > - } > - > - /* > - * Try to auto-detect the best slice; this should always give > - * a slice number > - */ > - if (dev->d_slice =3D=3D 0) { > - slice =3D disk_bestslice(slicetab, nslices); > - if (slice =3D=3D -1) { > - rc =3D ENOENT; > - goto out; > - } > - dev->d_slice =3D slice; > - } > - > - /* > - * Accept the supplied slice number unequivocally (we may be = looking > - * at a DOS partition). > - * Note: we number 1-4, offsets are 0-3 > - */ > - dptr =3D &slicetab[dev->d_slice - 1]; > - sector =3D dptr->dp_start; > - DEBUG("slice entry %d at %d, %d sectors", > - dev->d_slice - 1, sector, dptr->dp_size); > - > -unsliced: > - /* > - * Now we have the slice offset, look for the partition in the > - * disklabel if we have a partition to start with. > - * > - * XXX we might want to check the label checksum. > - */ > - if (dev->d_partition < 0) { > - /* no partition, must be after the slice */ > - DEBUG("opening raw slice"); > - dev->d_offset =3D sector; > - rc =3D 0; > - goto out; > - } > - > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, sector + = LABELSECTOR, > - DISK_SECSIZE, (char *) buf, NULL); > - if (rc) { > - DEBUG("error reading disklabel"); > - goto out; > - } > - > - lp =3D (struct disklabel *) buf; > - > - if (lp->d_magic !=3D DISKMAGIC) { > - DEBUG("no disklabel"); > - rc =3D ENOENT; > - goto out; > - } > - if (dev->d_partition >=3D lp->d_npartitions) { > - DEBUG("partition '%c' exceeds partitions in table = (a-'%c')", > - 'a' + dev->d_partition, > - 'a' + lp->d_npartitions); > - rc =3D EPART; > - goto out; > - } > - > - dev->d_offset =3D > - lp->d_partitions[dev->d_partition].p_offset - > - lp->d_partitions[RAW_PART].p_offset + > - sector; > - rc =3D 0; > - > -out: > - if (slicetab) > - free(slicetab); > - return (rc); > -} > - > -/* > - * Print out each valid partition in the disklabel of a FreeBSD = slice. > - * For size calculations, we assume a 512 byte sector size. > - */ > -static void > -disk_printbsdslice(struct disk_devdesc *dev, daddr_t offset, > - char *prefix, int verbose) > +ptblread(void *d, void *buf, size_t blocks, off_t offset) > { > - char line[80]; > - char buf[DISK_SECSIZE]; > - struct disklabel *lp; > - int i, rc, fstype; > - > - /* read disklabel */ > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, offset + = LABELSECTOR, > - DISK_SECSIZE, (char *) buf, NULL); > - if (rc) > - return; > - lp =3D(struct disklabel *)(&buf[0]); > - if (lp->d_magic !=3D DISKMAGIC) { > - sprintf(line, "%s: FFS bad disklabel\n", prefix); > - pager_output(line); > - return; > - } > + struct disk_devdesc *dev; > + struct open_disk *od; >=20 > - /* Print partitions */ > - for (i =3D 0; i < lp->d_npartitions; i++) { > - /* > - * For each partition, make sure we know what type of fs = it > - * is. If not, then skip it. > - */ > - fstype =3D lp->d_partitions[i].p_fstype; > - if (fstype !=3D FS_BSDFFS && > - fstype !=3D FS_SWAP && > - fstype !=3D FS_VINUM) > - continue; > - > - /* Only print out statistics in verbose mode */ > - if (verbose) > - sprintf(line, " %s%c: %s %s (%d - %d)\n", > - prefix, 'a' + i, > - (fstype =3D=3D FS_SWAP) ? "swap " : > - (fstype =3D=3D FS_VINUM) ? "vinum" : > - "FFS ", > - display_size(lp->d_partitions[i].p_size), > - lp->d_partitions[i].p_offset, > - (lp->d_partitions[i].p_offset > - + lp->d_partitions[i].p_size)); > - else > - sprintf(line, " %s%c: %s\n", prefix, 'a' + i, > - (fstype =3D=3D FS_SWAP) ? "swap" : > - (fstype =3D=3D FS_VINUM) ? "vinum" : > - "FFS"); > - pager_output(line); > - } > + dev =3D (struct disk_devdesc *)d; > + od =3D (struct open_disk *)dev->d_opendata; > + return (dev->d_dev->dv_strategy(dev, F_READ, offset, > + blocks * od->sectorsize, (char *)buf, NULL)); > } >=20 > +#define PWIDTH 35 > static void > -disk_printslice(struct disk_devdesc *dev, int slice, > - struct dos_partition *dp, char *prefix, int verbose) > +ptable_print(void *arg, const char *pname, const struct ptable_entry = *part) > { > - char stats[80]; > + struct print_args *pa, bsd; > + struct open_disk *od; > + struct ptable *table; > char line[80]; >=20 > - if (verbose) > - sprintf(stats, " %s (%d - %d)", = display_size(dp->dp_size), > - dp->dp_start, dp->dp_start + dp->dp_size); > - else > - stats[0] =3D '\0'; > - > - switch (dp->dp_typ) { > - case DOSPTYP_386BSD: > - disk_printbsdslice(dev, (daddr_t)dp->dp_start, > - prefix, verbose); > - return; > - case DOSPTYP_LINSWP: > - sprintf(line, "%s: Linux swap%s\n", prefix, stats); > - break; > - case DOSPTYP_LINUX: > - /* > - * XXX > - * read the superblock to confirm this is an ext2fs = partition? > - */ > - sprintf(line, "%s: ext2fs%s\n", prefix, stats); > - break; > - case 0x00: /* unused partition */ > - case DOSPTYP_EXT: > - return; > - case 0x01: > - sprintf(line, "%s: FAT-12%s\n", prefix, stats); > - break; > - case 0x04: > - case 0x06: > - case 0x0e: > - sprintf(line, "%s: FAT-16%s\n", prefix, stats); > - break; > - case 0x07: > - sprintf(line, "%s: NTFS/HPFS%s\n", prefix, stats); > - break; > - case 0x0b: > - case 0x0c: > - sprintf(line, "%s: FAT-32%s\n", prefix, stats); > - break; > - default: > - sprintf(line, "%s: Unknown fs: 0x%x %s\n", prefix, = dp->dp_typ, > - stats); > - } > + pa =3D (struct print_args *)arg; > + od =3D (struct open_disk *)pa->dev->d_opendata; > + sprintf(line, " %s%s: %s", pa->prefix, pname, > + parttype2str(part->type)); > + if (pa->verbose) > + sprintf(line, "%-*s%s", PWIDTH, line, > + display_size(part->end - part->start + 1, > + od->sectorsize)); > + strcat(line, "\n"); > pager_output(line); > -} > - > -static int > -disk_printmbr(struct disk_devdesc *dev, char *prefix, int verbose) > -{ > - struct dos_partition *slicetab; > - int nslices, i; > - int rc; > - char line[80]; > - > - rc =3D disk_readslicetab(dev, &slicetab, &nslices); > - if (rc) > - return (rc); > - for (i =3D 0; i < nslices; i++) { > - sprintf(line, "%ss%d", prefix, i + 1); > - disk_printslice(dev, i, &slicetab[i], line, verbose); > - } > - free(slicetab); > - return (0); > -} > - > -#endif > - > -#ifdef LOADER_GPT_SUPPORT > - > -static int > -disk_readgpt(struct disk_devdesc *dev, struct gpt_part **gptp, int = *ngptp) > -{ > - struct dos_partition *dp; > - struct gpt_hdr *hdr; > - struct gpt_ent *ent; > - struct gpt_part *gptab =3D NULL; > - int entries_per_sec, rc, i, part; > - daddr_t lba, elba; > - uint8_t gpt[DISK_SECSIZE], tbl[DISK_SECSIZE]; > - > - /* > - * Following calculations attempt to determine the correct value > - * for dev->d_offset by looking for the slice and partition = specified, > - * or searching for reasonable defaults. > - */ > - rc =3D 0; > - > - /* First, read the MBR and see if we have a PMBR. */ > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, 0, DISK_SECSIZE, > - (char *) tbl, NULL); > - if (rc) { > - DEBUG("error reading MBR"); > - return (EIO); > + if (part->type =3D=3D PART_FREEBSD) { > + /* Open slice with BSD label */ > + pa->dev->d_offset =3D part->start; > + table =3D ptable_open(pa->dev, part->end - part->start + = 1, > + od->sectorsize, ptblread); > + if (table =3D=3D NULL) > + return; > + sprintf(line, " %s%s", pa->prefix, pname); > + bsd.dev =3D pa->dev; > + bsd.prefix =3D line; > + bsd.verbose =3D pa->verbose; > + ptable_iterate(table, &bsd, ptable_print); > + ptable_close(table); > } > - > - /* Check the slice table magic. */ > - if (tbl[0x1fe] !=3D 0x55 || tbl[0x1ff] !=3D 0xaa) > - return (ENXIO); > - > - /* Check for GPT slice. */ > - part =3D 0; > - dp =3D (struct dos_partition *)(tbl + DOSPARTOFF); > - for (i =3D 0; i < NDOSPART; i++) { > - if (dp[i].dp_typ =3D=3D 0xee) > - part++; > - else if ((part !=3D 1) && (dp[i].dp_typ !=3D 0x00)) > - return (EINVAL); > - } > - if (part !=3D 1) > - return (EINVAL); > - > - /* Read primary GPT table header. */ > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, 1, DISK_SECSIZE, > - (char *) gpt, NULL); > - if (rc) { > - DEBUG("error reading GPT header"); > - return (EIO); > - } > - hdr =3D (struct gpt_hdr *)gpt; > - if (bcmp(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig)) !=3D 0 = || > - hdr->hdr_lba_self !=3D 1 || hdr->hdr_revision < 0x00010000 = || > - hdr->hdr_entsz < sizeof(*ent) || > - DISK_SECSIZE % hdr->hdr_entsz !=3D 0) { > - DEBUG("Invalid GPT header\n"); > - return (EINVAL); > - } > - > - /* Walk the partition table to count valid partitions. */ > - part =3D 0; > - entries_per_sec =3D DISK_SECSIZE / hdr->hdr_entsz; > - elba =3D hdr->hdr_lba_table + hdr->hdr_entries / = entries_per_sec; > - for (lba =3D hdr->hdr_lba_table; lba < elba; lba++) { > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, lba, = DISK_SECSIZE, > - (char *) tbl, NULL); > - if (rc) { > - DEBUG("error reading GPT table"); > - return (EIO); > - } > - for (i =3D 0; i < entries_per_sec; i++) { > - ent =3D (struct gpt_ent *)(tbl + i * = hdr->hdr_entsz); > - if (uuid_is_nil(&ent->ent_type, NULL) || > - ent->ent_lba_start =3D=3D 0 || > - ent->ent_lba_end < ent->ent_lba_start) > - continue; > - part++; > - } > - } > - > - /* Save the important information about all the valid = partitions. */ > - if (part !=3D 0) { > - gptab =3D malloc(part * sizeof(struct gpt_part)); > - part =3D 0; > - for (lba =3D hdr->hdr_lba_table; lba < elba; lba++) { > - rc =3D dev->d_dev->dv_strategy(dev, F_READ, lba, = DISK_SECSIZE, > - (char *) tbl, NULL); > - if (rc) { > - DEBUG("error reading GPT table"); > - free(gptab); > - return (EIO); > - } > - for (i =3D 0; i < entries_per_sec; i++) { > - ent =3D (struct gpt_ent *)(tbl + i * = hdr->hdr_entsz); > - if (uuid_is_nil(&ent->ent_type, NULL) || > - ent->ent_lba_start =3D=3D 0 || > - ent->ent_lba_end < = ent->ent_lba_start) > - continue; > - gptab[part].gp_index =3D (lba - = hdr->hdr_lba_table) * > - entries_per_sec + i + 1; > - gptab[part].gp_type =3D ent->ent_type; > - gptab[part].gp_start =3D = ent->ent_lba_start; > - gptab[part].gp_end =3D ent->ent_lba_end; > - part++; > - } > - } > - } > - > - *gptp =3D gptab; > - *ngptp =3D part; > - return (0); > } > +#undef PWIDTH >=20 > -static struct gpt_part * > -disk_bestgpt(struct gpt_part *gpt, int ngpt) > +void > +disk_print(struct disk_devdesc *dev, char *prefix, int verbose) > { > - struct gpt_part *gp, *prefpart; > - int i, pref, preflevel; > - > - prefpart =3D NULL; > - preflevel =3D PREF_NONE; > + struct open_disk *od; > + struct print_args pa; >=20 > - gp =3D gpt; > - for (i =3D 0; i < ngpt; i++, gp++) { > - /* Windows. XXX: Also Linux. */ > - if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL)) > - pref =3D PREF_DOS; > - /* FreeBSD */ > - else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL) || > - uuid_equal(&gp->gp_type, &freebsd_zfs, NULL)) > - pref =3D PREF_FBSD; > - else > - pref =3D PREF_NONE; > - if (pref < preflevel) { > - preflevel =3D pref; > - prefpart =3D gp; > - } > - } > - return (prefpart); > + /* Disk should be opened */ > + od =3D (struct open_disk *)dev->d_opendata; > + pa.dev =3D dev; > + pa.prefix =3D prefix; > + pa.verbose =3D verbose; > + ptable_iterate(od->table, &pa, ptable_print); > } >=20 > -static int > -disk_opengpt(struct disk_devdesc *dev) > +int > +disk_open(struct disk_devdesc *dev, off_t mediasize, u_int = sectorsize) > { > - struct gpt_part *gpt =3D NULL, *gp; > - int rc, ngpt, i; > + struct open_disk *od; > + struct ptable *table; > + struct ptable_entry part; > + int rc; >=20 > - rc =3D disk_readgpt(dev, &gpt, &ngpt); > - if (rc) > - return (rc); > - > - /* Is this a request for the whole disk? */ > - if (dev->d_slice < 0) { > - dev->d_offset =3D 0; > - rc =3D 0; > - goto out; > + od =3D (struct open_disk *)malloc(sizeof(struct open_disk)); > + if (od =3D=3D NULL) { > + DEBUG("no memory"); > + return (ENOMEM); > } > - > /* > - * If a partition number was supplied, then the user is trying = to use > - * an MBR address rather than a GPT address, so fail. > + * While we are reading disk metadata, make sure we do it = relative > + * to the start of the disk > */ > - if (dev->d_partition !=3D 0xff) { > - rc =3D ENOENT; > + rc =3D 0; > + table =3D NULL; > + dev->d_offset =3D 0; > + dev->d_opendata =3D od; > + od->mediasize =3D mediasize; > + od->sectorsize =3D sectorsize; > + DEBUG("open '%s', unit %d slice %d partition %d", > + disk_fmtdev(dev), dev->d_unit, dev->d_slice, = dev->d_partition); > + > + /* Determine disk layout. */ > + od->table =3D ptable_open(dev, mediasize / sectorsize, = sectorsize, > + ptblread); > + if (od->table =3D=3D NULL) { > + DEBUG("Can't read partition table"); > + rc =3D ENXIO; > goto out; > } > - > - /* If a slice number was supplied but not found, this is an = error. */ > - gp =3D NULL; > if (dev->d_slice > 0) { > - for (i =3D 0; i < ngpt; i++) { > - if (gpt[i].gp_index =3D=3D dev->d_slice) { > - gp =3D &gpt[i]; > - break; > - } > - } > - if (gp =3D=3D NULL) { > - DEBUG("partition %d not found", dev->d_slice); > - rc =3D ENOENT; > + /* Try to get information about partition */ > + rc =3D ptable_getpart(od->table, &part, dev->d_slice); > + if (rc !=3D 0) /* Partition doesn't exist */ > goto out; > - } > - } > - > - /* Try to auto-detect the best partition. */ > - if (dev->d_slice =3D=3D 0) { > - gp =3D disk_bestgpt(gpt, ngpt); > - if (gp =3D=3D NULL) { > - rc =3D ENOENT; > + dev->d_offset =3D part.start; > + if (dev->d_partition =3D=3D -1 || > + dev->d_partition =3D=3D 255) > + goto out; /* Nothing more to do */ > + > + /* Try to read BSD label */ > + table =3D ptable_open(dev, part.end - part.start + 1, > + od->sectorsize, ptblread); > + if (table =3D=3D NULL) { > + DEBUG("Can't read BSD label"); > + rc =3D ENXIO; > goto out; > } > - dev->d_slice =3D gp->gp_index; > + rc =3D ptable_getpart(table, &part, dev->d_partition); > + if (rc !=3D 0) > + goto out; > + dev->d_offset +=3D part.start; > + } else if (dev->d_slice =3D=3D 0) { > + rc =3D ptable_getbestpart(od->table, &part); > + if (rc !=3D 0) > + goto out; > + /* Save the slice number of best partition to dev */ > + dev->d_slice =3D part.index; > + dev->d_offset =3D part.start; > } > - > - dev->d_offset =3D gp->gp_start; > - rc =3D 0; > - > out: > - if (gpt) > - free(gpt); > + if (table !=3D NULL) > + ptable_close(table); > + if (rc !=3D 0) { > + if (od->table !=3D NULL) > + ptable_close(od->table); > + free(od); > + } > return (rc); > } >=20 > -static void > -disk_printgptpart(struct disk_devdesc *dev, struct gpt_part *gp, > - char *prefix, int verbose) > +int > +disk_close(struct disk_devdesc *dev) > { > - char stats[80]; > - char line[96]; > - > - if (verbose) > - sprintf(stats, " %s", > - display_size(gp->gp_end + 1 - gp->gp_start)); > - else > - stats[0] =3D '\0'; > - > - if (uuid_equal(&gp->gp_type, &efi, NULL)) > - sprintf(line, "%s: EFI %s\n", prefix, stats); > - else if (uuid_equal(&gp->gp_type, &ms_basic_data, NULL)) > - sprintf(line, "%s: FAT/NTFS %s\n", prefix, stats); > - else if (uuid_equal(&gp->gp_type, &freebsd_boot, NULL)) > - sprintf(line, "%s: FreeBSD boot%s\n", prefix, stats); > - else if (uuid_equal(&gp->gp_type, &freebsd_ufs, NULL)) > - sprintf(line, "%s: FreeBSD UFS %s\n", prefix, stats); > - else if (uuid_equal(&gp->gp_type, &freebsd_zfs, NULL)) > - sprintf(line, "%s: FreeBSD ZFS %s\n", prefix, stats); > - else if (uuid_equal(&gp->gp_type, &freebsd_swap, NULL)) > - sprintf(line, "%s: FreeBSD swap%s\n", prefix, stats); > - else > - sprintf(line, > - "%s: = %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x%s\n", > - prefix, > - gp->gp_type.time_low, gp->gp_type.time_mid, > - gp->gp_type.time_hi_and_version, > - gp->gp_type.clock_seq_hi_and_reserved, > - gp->gp_type.clock_seq_low, > - gp->gp_type.node[0], > - gp->gp_type.node[1], > - gp->gp_type.node[2], > - gp->gp_type.node[3], > - gp->gp_type.node[4], > - gp->gp_type.node[5], > - stats); > - pager_output(line); > -} > + struct open_disk *od; >=20 > -static int > -disk_printgpt(struct disk_devdesc *dev, char *prefix, int verbose) > -{ > - struct gpt_part *gpt =3D NULL; > - int rc, ngpt, i; > - char line[80]; > - > - rc =3D disk_readgpt(dev, &gpt, &ngpt); > - if (rc) > - return (rc); > - for (i =3D 0; i < ngpt; i++) { > - sprintf(line, "%sp%d", prefix, i + 1); > - disk_printgptpart(dev, &gpt[i], line, verbose); > - } > - free(gpt); > + od =3D (struct open_disk *)dev->d_opendata; > + ptable_close(od->table); > + free(od); > return (0); > } >=20 > -#endif > - > -int > -disk_open(struct disk_devdesc *dev) > +char* > +disk_fmtdev(struct disk_devdesc *dev) > { > - int rc; > - > - rc =3D 0; > - /* > - * While we are reading disk metadata, make sure we do it = relative > - * to the start of the disk > - */ > - dev->d_offset =3D 0; > + static char buf[128]; > + char *cp; >=20 > + cp =3D buf + sprintf(buf, "%s%d", dev->d_dev->dv_name, = dev->d_unit); > + if (dev->d_slice > 0) { > #ifdef LOADER_GPT_SUPPORT > - rc =3D disk_opengpt(dev); > - if (rc =3D=3D 0) > - return (0); > + if (dev->d_partition =3D=3D 255) { > + sprintf(cp, "p%d:", dev->d_slice); > + return (buf); > + } else > #endif > #ifdef LOADER_MBR_SUPPORT > - rc =3D disk_openmbr(dev); > + cp +=3D sprintf(cp, "s%d", dev->d_slice); > #endif > - > - return (rc); > + if (dev->d_partition >=3D 0) > + cp +=3D sprintf(cp, "%c", dev->d_partition + = 'a'); > + } > + strcat(cp, ":"); > + return (buf); > } >=20 > -void > -disk_print(struct disk_devdesc *dev, char *prefix, int verbose) > +int > +disk_parsedev(struct disk_devdesc *dev, const char *devspec, const = char **path) > { > - > + int unit, slice, partition; > + const char *np; > + char *cp; > + > + np =3D devspec; > + unit =3D slice =3D partition =3D -1; > + if (*np !=3D '\0' && *np !=3D ':') { > + unit =3D strtol(np, &cp, 10); > + if (cp =3D=3D np) > + return (EUNIT); > #ifdef LOADER_GPT_SUPPORT > - if (disk_printgpt(dev, prefix, verbose) =3D=3D 0) > - return; > + if (*cp =3D=3D 'p') { > + np =3D cp + 1; > + slice =3D strtol(np, &cp, 10); > + if (np =3D=3D cp) > + return (ESLICE); > + /* we don't support nested partitions on GPT */ > + if (*cp !=3D '\0' && *cp !=3D ':') > + return (EINVAL); > + partition =3D 255; > + } else > #endif > #ifdef LOADER_MBR_SUPPORT > - disk_printmbr(dev, prefix, verbose); > + if (*cp =3D=3D 's') { > + np =3D cp + 1; > + slice =3D strtol(np, &cp, 10); > + if (np =3D=3D cp) > + return (ESLICE); > + } > #endif > + if (*cp !=3D '\0' && *cp !=3D ':') { > + partition =3D *cp - 'a'; > + if (partition < 0) > + return (EPART); > + cp++; > + } > + } else > + return (EINVAL); > + > + if (*cp !=3D '\0' && *cp !=3D ':') > + return (EINVAL); > + dev->d_unit =3D unit; > + dev->d_slice =3D slice; > + dev->d_partition =3D partition; > + if (path !=3D NULL) > + *path =3D (*cp =3D=3D '\0') ? cp: cp + 1; > + return (0); > } >=20 > Modified: head/sys/boot/common/disk.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- head/sys/boot/common/disk.h Sun Aug 5 11:59:46 2012 = (r239057) > +++ head/sys/boot/common/disk.h Sun Aug 5 12:15:15 2012 = (r239058) > @@ -27,8 +27,7 @@ > */ >=20 > /* > - * Device descriptor for partitioned disks. We assume that all disk = addresses >=20 > *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?050317CF-D855-4DA4-B15E-E032905260D5>