]> Zhao Yanbai Git Server - minix.git/commitdiff
installboot: allow installation into disk
authorDavid van Moolenbroek <david@minix3.org>
Sat, 9 Feb 2013 23:44:44 +0000 (00:44 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Sat, 16 Feb 2013 21:58:53 +0000 (22:58 +0100)
Previously, installboot would require that the given target device is
a partition. This is not strictly necessary: MINIX3 can also be
installed (manually) into one or more primary partitions, requiring
that the installboot target be the entire disk. With this patch,
specifying a disk as target is now allowed, as long as the -f (force)
option is given.

usr.sbin/installboot/installboot.c
usr.sbin/installboot/installboot.h
usr.sbin/installboot/minixfs3.c

index c4e6a7a0ef037ce3bfbdef825c8f3ad8fb979a7b..f3867a9c7b128b68a452399fa65a687e8642e2fe 100644 (file)
@@ -245,13 +245,13 @@ main(int argc, char *argv[])
                mode = O_RDWR;
        }
 
-       if (minixfs3_is_minix_partition(params->filesystem)) {
+       if (minixfs3_is_minix_partition(params)) {
                /* Old setups has just 1 sector for bootblock,
                 * but bootxx_minixfs is ~8Kb, so we require new setups
                 * to have 32 sectors before the first subpartition.
                 * This prevents from overwriting FS on old setups.
                 */
-               if (!minixfs3_has_bootblock_space(params->filesystem)) {
+               if (!minixfs3_has_bootblock_space(params)) {
                        err(1, "No space for bootxx, you should have 32 sectors"
                                " before the first subpartition on %s",
                                params->filesystem);
index c66fc2ec9f404a820b81fe01ec675744abe52030..f12ec8e9b434430c8c7c4597c75791648662c399 100644 (file)
@@ -166,8 +166,8 @@ void                install_master(const char *device, char *masterboot, char **guide);
 int            isoption(const char *option, const char *test);
 
        /* minixfs3.c */
-int minixfs3_is_minix_partition(const char* partition);
-int minixfs3_has_bootblock_space(const char* partition);
+int minixfs3_is_minix_partition(ib_params *params);
+int minixfs3_has_bootblock_space(ib_params *params);
 
 
        /* machines.c */
@@ -178,9 +178,6 @@ extern struct ib_mach ib_mach_ews4800mips;
 extern struct ib_mach ib_mach_hp300;
 extern struct ib_mach ib_mach_hp700;
 extern struct ib_mach ib_mach_i386;
-#ifdef __minix
-extern struct ib_mach ib_mach_i386;
-#endif
 extern struct ib_mach ib_mach_landisk;
 extern struct ib_mach ib_mach_macppc;
 extern struct ib_mach ib_mach_news68k;
index 1951b89bfc134f1119b7dc0a22e04c6611c92872..8009e5a8907f7601cbcfd76354e75f9d2d8c5a82 100644 (file)
 
 #define MFS_FIRST_SUBP_OFFSET  32
 
-static int minixfs3_read_mbr(const char* device, char* buf)
+enum {
+       TYPE_BAD,
+       TYPE_PART,
+       TYPE_DISK
+};
+
+static int
+minixfs3_read_mbr(const char* device, char* buf)
 {
        int fd;
        int bytes;
@@ -56,30 +63,48 @@ static int minixfs3_read_mbr(const char* device, char* buf)
        return 0;
 }
 
-
-int minixfs3_is_minix_partition(const char* partition)
+static int
+minixfs3_get_dev_type(const char *device, ib_params *params)
 {
-       char buf[DFL_SECSIZE]; /* part table + signature */
-       int name_length = strlen(partition);
+       int len, type;
+
+       /*
+        * Unless the -f flag is given, we expect to be provided with a primary
+        * partition.  That is, a device name that ends with "pN", N being 0-3.
+        * If the -f flag is given, we assume that anything else is a whole
+        * disk.  If we were given a subpartition, it will fail the subsequent
+        * MBR signature test, so we need not check this explicitly.
+        */
+       len = strlen(device);
 
-       /* partition must be 0-3 */
-       if (atol(&partition[name_length-1]) >= 4) {
-               fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n",
-                       partition);
-               return 0;
+       if (len > 2 && device[len-2] == 'p' &&
+           (unsigned) (device[len-1] - '0') <= 3) {
+               type = TYPE_PART;
+       } else {
+               type = TYPE_DISK;
        }
 
-       /* it should be partition device, not disk */
-       if (partition[name_length-2] != 'p') {
+       if (type != TYPE_PART && !(params->flags & IB_FORCE)) {
                fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n",
-                       partition);
-               return 0;
+                       device);
+               return TYPE_BAD;
        }
 
+       return type;
+}
+
+int
+minixfs3_is_minix_partition(ib_params *params)
+{
+       char buf[DFL_SECSIZE]; /* part table + signature */
+
+       if (minixfs3_get_dev_type(params->filesystem, params) == TYPE_BAD)
+               return 0;
+
        /* MINIX 3 partition with current scheme *must* have subpartitions,
         * thus MBR has signature. minixfs3_read_mbr checks the signature.
         */
-       if (minixfs3_read_mbr(partition, buf))
+       if (minixfs3_read_mbr(params->filesystem, buf))
                return 0;
        return 1;
 }
@@ -89,52 +114,55 @@ int minixfs3_is_minix_partition(const char* partition)
  * to install bootxx_minixfs3. New installation should have 16Kb before
  * the first subpartition.
  */
-int minixfs3_has_bootblock_space(const char* partition)
+int
+minixfs3_has_bootblock_space(ib_params *params)
 {
+       const char *device;
        char buf[DFL_SECSIZE]; /* part table + signature */
-       char disk[NAME_MAX];
+       char parent_name[NAME_MAX];
        struct mbr_partition *part;
        uint32_t first_subpartition = (uint32_t) ~0;
-       uint32_t parent_partition = 0;
-       int i;
-       int name_length = strlen(partition);
+       uint32_t parent_partition;
+       int i, len, type = 0;
 
-       /* partition must be 0-3 */
-       if (atol(&partition[name_length-1]) >= 4) {
-               fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n",
-                       partition);
-               exit(1);
-       }
-       /* it should be partition device, not disk */
-       if (partition[name_length-2] != 'p') {
-               fprintf(stderr, "Wrong device %s, must be /.../cxdyp[0-3]\n",
-                       partition);
+       device = params->filesystem;
+
+       if ((type = minixfs3_get_dev_type(device, params)) == TYPE_BAD)
                exit(1);
-       }
 
-       if (minixfs3_read_mbr(partition, buf))
+       if (minixfs3_read_mbr(device, buf))
                exit(1);
 
        part = (struct mbr_partition *) buf;
 
        for (i = 0; i < 4; i++) {
-               if (part[i].mbrp_size && part[i].mbrp_start < first_subpartition)
+               if (part[i].mbrp_size &&
+                   part[i].mbrp_start < first_subpartition)
                        first_subpartition = part[i].mbrp_start;
        }
 
-       strncpy(disk, partition, name_length - 2);
-       disk[name_length - 2] = '\0';
-
-       if (minixfs3_read_mbr(disk, buf))
-               exit(1);
-
-       for (i = 0; i < 4; i++) {
-               struct mbr_partition *p = &part[i];
-               if (p->mbrp_size && p->mbrp_start <= first_subpartition
-                   && (p->mbrp_start + p->mbrp_size) > first_subpartition) {
-                       parent_partition = p->mbrp_start;
-                       break;
+       if (type == TYPE_PART) {
+               /* The target is a partition.  Look up its starting offset. */
+               len = strlen(device);
+               strncpy(parent_name, device, len - 2);
+               parent_name[len - 2] = '\0';
+
+               if (minixfs3_read_mbr(parent_name, buf))
+                       exit(1);
+
+               parent_partition = 0;
+               for (i = 0; i < 4; i++) {
+                       struct mbr_partition *p = &part[i];
+                       if (p->mbrp_size && p->mbrp_start <= first_subpartition
+                           && (p->mbrp_start + p->mbrp_size) >
+                           first_subpartition) {
+                               parent_partition = p->mbrp_start;
+                               break;
+                       }
                }
+       } else {
+               /* The target is a whole disk.  The starting offset is 0. */
+               parent_partition = 0;
        }
 
        if ((first_subpartition - parent_partition) < MFS_FIRST_SUBP_OFFSET)