[BACK]Return to migrate.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / gpt

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sbin/gpt/migrate.c between version 1.22 and 1.23

version 1.22, 2015/11/29 00:14:46 version 1.23, 2015/12/01 09:05:33
Line 55  __RCSID("$NetBSD$");
Line 55  __RCSID("$NetBSD$");
   
 #include "map.h"  #include "map.h"
 #include "gpt.h"  #include "gpt.h"
   #include "gpt_private.h"
   
 /*  /*
  * Allow compilation on platforms that do not have a BSD label.   * Allow compilation on platforms that do not have a BSD label.
Line 77  __RCSID("$NetBSD$");
Line 78  __RCSID("$NetBSD$");
   
 static int force;  static int force;
 static int slice;  static int slice;
   static u_int parts;
   
 const char migratemsg[] = "migrate [-fs] device ...";  const char migratemsg[] = "migrate [-fs] [-p <partitions>]";
   
 __dead static void  static int
 usage_migrate(void)  usage_migrate(void)
 {  {
   
         fprintf(stderr,          fprintf(stderr,
             "usage: %s %s\n", getprogname(), migratemsg);              "usage: %s %s\n", getprogname(), migratemsg);
         exit(1);          return -1;
 }  }
   
 static struct gpt_ent*  static struct gpt_ent *
 migrate_disklabel(int fd, off_t start, struct gpt_ent *ent)  migrate_disklabel(gpt_t gpt, off_t start, struct gpt_ent *ent)
 {  {
         char *buf;          char *buf;
         struct disklabel *dl;          struct disklabel *dl;
         off_t ofs, rawofs;          off_t ofs, rawofs;
         int i;          int i;
   
         buf = gpt_read(fd, start + LABELSECTOR, 1);          buf = gpt_read(gpt, start + LABELSECTOR, 1);
           if (buf == NULL) {
                   gpt_warn(gpt, "Error reading label");
                   return NULL;
           }
         dl = (void*)(buf + LABELOFFSET);          dl = (void*)(buf + LABELOFFSET);
   
         if (le32toh(dl->d_magic) != DISKMAGIC ||          if (le32toh(dl->d_magic) != DISKMAGIC ||
             le32toh(dl->d_magic2) != DISKMAGIC) {              le32toh(dl->d_magic2) != DISKMAGIC) {
                 warnx("%s: warning: FreeBSD slice without disklabel",                  gpt_warnx(gpt, "FreeBSD slice without disklabel");
                     device_name);  
                 free(buf);                  free(buf);
                 return (ent);                  return (ent);
         }          }
Line 118  migrate_disklabel(int fd, off_t start, s
Line 123  migrate_disklabel(int fd, off_t start, s
                 if (ofs < rawofs)                  if (ofs < rawofs)
                         rawofs = 0;                          rawofs = 0;
         }          }
         rawofs /= secsz;          rawofs /= gpt->secsz;
   
         for (i = 0; i < le16toh(dl->d_npartitions); i++) {          for (i = 0; i < le16toh(dl->d_npartitions); i++) {
                 switch (dl->d_partitions[i].p_fstype) {                  switch (dl->d_partitions[i].p_fstype) {
Line 145  migrate_disklabel(int fd, off_t start, s
Line 150  migrate_disklabel(int fd, off_t start, s
                         break;                          break;
                 }                  }
                 default:                  default:
                         warnx("%s: warning: unknown FreeBSD partition (%d)",                          gpt_warnx(gpt, "Unknown FreeBSD partition (%d)",
                             device_name, dl->d_partitions[i].p_fstype);                              dl->d_partitions[i].p_fstype);
                         continue;                          continue;
                 }                  }
   
                 ofs = (le32toh(dl->d_partitions[i].p_offset) *                  ofs = (le32toh(dl->d_partitions[i].p_offset) *
                     le32toh(dl->d_secsize)) / secsz;                      le32toh(dl->d_secsize)) / gpt->secsz;
                 ofs = (ofs > 0) ? ofs - rawofs : 0;                  ofs = (ofs > 0) ? ofs - rawofs : 0;
                 ent->ent_lba_start = htole64(start + ofs);                  ent->ent_lba_start = htole64(start + ofs);
                 ent->ent_lba_end = htole64(start + ofs +                  ent->ent_lba_end = htole64(start + ofs +
Line 160  migrate_disklabel(int fd, off_t start, s
Line 165  migrate_disklabel(int fd, off_t start, s
         }          }
   
         free(buf);          free(buf);
         return (ent);          return ent;
 }  }
   
 static struct gpt_ent*  static struct gpt_ent*
 migrate_netbsd_disklabel(int fd, off_t start, struct gpt_ent *ent)  migrate_netbsd_disklabel(gpt_t gpt, off_t start, struct gpt_ent *ent)
 {  {
         char *buf;          char *buf;
         struct disklabel *dl;          struct disklabel *dl;
         off_t ofs, rawofs;          off_t ofs, rawofs;
         int i;          int i;
   
         buf = gpt_read(fd, start + LABELSECTOR, 1);          buf = gpt_read(gpt, start + LABELSECTOR, 1);
           if (buf == NULL) {
                   gpt_warn(gpt, "Error reading label");
                   return NULL;
           }
         dl = (void*)(buf + LABELOFFSET);          dl = (void*)(buf + LABELOFFSET);
   
         if (le32toh(dl->d_magic) != DISKMAGIC ||          if (le32toh(dl->d_magic) != DISKMAGIC ||
             le32toh(dl->d_magic2) != DISKMAGIC) {              le32toh(dl->d_magic2) != DISKMAGIC) {
                 warnx("%s: warning: NetBSD slice without disklabel",                  gpt_warnx(gpt, "NetBSD slice without disklabel");
                     device_name);  
                 free(buf);                  free(buf);
                 return (ent);                  return ent;
         }          }
   
         rawofs = le32toh(dl->d_partitions[RAW_PART].p_offset) *          rawofs = le32toh(dl->d_partitions[RAW_PART].p_offset) *
Line 192  migrate_netbsd_disklabel(int fd, off_t s
Line 200  migrate_netbsd_disklabel(int fd, off_t s
                 if (ofs < rawofs)                  if (ofs < rawofs)
                         rawofs = 0;                          rawofs = 0;
         }          }
         rawofs /= secsz;          rawofs /= gpt->secsz;
   
         for (i = 0; i < le16toh(dl->d_npartitions); i++) {          for (i = 0; i < le16toh(dl->d_npartitions); i++) {
                 switch (dl->d_partitions[i].p_fstype) {                  switch (dl->d_partitions[i].p_fstype) {
Line 229  migrate_netbsd_disklabel(int fd, off_t s
Line 237  migrate_netbsd_disklabel(int fd, off_t s
                         break;                          break;
                 }                  }
                 default:                  default:
                         warnx("%s: warning: unknown NetBSD partition (%d)",                          gpt_warnx(gpt, "Unknown NetBSD partition (%d)",
                             device_name, dl->d_partitions[i].p_fstype);                              dl->d_partitions[i].p_fstype);
                         continue;                          continue;
                 }                  }
   
                 ofs = (le32toh(dl->d_partitions[i].p_offset) *                  ofs = (le32toh(dl->d_partitions[i].p_offset) *
                     le32toh(dl->d_secsize)) / secsz;                      le32toh(dl->d_secsize)) / gpt->secsz;
                 ofs = (ofs > 0) ? ofs - rawofs : 0;                  ofs = (ofs > 0) ? ofs - rawofs : 0;
                 ent->ent_lba_start = htole64(ofs);                  ent->ent_lba_start = htole64(ofs);
                 ent->ent_lba_end = htole64(ofs +                  ent->ent_lba_end = htole64(ofs +
Line 244  migrate_netbsd_disklabel(int fd, off_t s
Line 252  migrate_netbsd_disklabel(int fd, off_t s
         }          }
   
         free(buf);          free(buf);
         return (ent);          return ent;
 }  }
   
 static void  static int
 migrate(int fd)  migrate(gpt_t gpt)
 {  {
         off_t blocks, last;          off_t blocks, last;
         map_t *gpt, *tpg;          map_t map;
         map_t *tbl, *lbt;  
         map_t *map;  
         struct gpt_hdr *hdr;          struct gpt_hdr *hdr;
         struct gpt_ent *ent;          struct gpt_ent *ent;
         struct mbr *mbr;          struct mbr *mbr;
         uint32_t start, size;          uint32_t start, size;
         unsigned int i;          unsigned int i;
   
         last = mediasz / secsz - 1LL;          last = gpt->mediasz / gpt->secsz - 1LL;
   
         map = map_find(MAP_TYPE_MBR);          map = map_find(gpt, MAP_TYPE_MBR);
         if (map == NULL || map->map_start != 0) {          if (map == NULL || map->map_start != 0) {
                 warnx("%s: error: no partitions to convert", device_name);                  gpt_warnx(gpt, "No partitions to convert");
                 return;                  return -1;
         }          }
   
         mbr = map->map_data;          mbr = map->map_data;
   
         if (map_find(MAP_TYPE_PRI_GPT_HDR) != NULL ||          if (map_find(gpt, MAP_TYPE_PRI_GPT_HDR) != NULL ||
             map_find(MAP_TYPE_SEC_GPT_HDR) != NULL) {              map_find(gpt, MAP_TYPE_SEC_GPT_HDR) != NULL) {
                 warnx("%s: error: device already contains a GPT", device_name);                  gpt_warnx(gpt, "Device already contains a GPT");
                 return;                  return -1;
         }          }
   
         /* Get the amount of free space after the MBR */          /* Get the amount of free space after the MBR */
         blocks = map_free(1LL, 0LL);          blocks = map_free(gpt, 1LL, 0LL);
         if (blocks == 0LL) {          if (blocks == 0LL) {
                 warnx("%s: error: no room for the GPT header", device_name);                  gpt_warnx(gpt, "No room for the GPT header");
                 return;                  return -1;
         }          }
   
         /* Don't create more than parts entries. */          /* Don't create more than parts entries. */
         if ((uint64_t)(blocks - 1) * secsz > parts * sizeof(struct gpt_ent)) {          if ((uint64_t)(blocks - 1) * gpt->secsz >
                 blocks = (parts * sizeof(struct gpt_ent)) / secsz;              parts * sizeof(struct gpt_ent)) {
                 if ((parts * sizeof(struct gpt_ent)) % secsz)                  blocks = (parts * sizeof(struct gpt_ent)) / gpt->secsz;
                   if ((parts * sizeof(struct gpt_ent)) % gpt->secsz)
                         blocks++;                          blocks++;
                 blocks++;               /* Don't forget the header itself */                  blocks++;               /* Don't forget the header itself */
         }          }
Line 299  migrate(int fd)
Line 306  migrate(int fd)
          * Get the amount of free space at the end of the device and           * Get the amount of free space at the end of the device and
          * calculate the size for the GPT structures.           * calculate the size for the GPT structures.
          */           */
         map = map_last();          map = map_last(gpt);
         if (map->map_type != MAP_TYPE_UNUSED) {          if (map->map_type != MAP_TYPE_UNUSED) {
                 warnx("%s: error: no room for the backup header", device_name);                  gpt_warnx(gpt, "No room for the backup header");
                 return;                  return -1;
         }          }
   
         if (map->map_size < blocks)          if (map->map_size < blocks)
                 blocks = map->map_size;                  blocks = map->map_size;
         if (blocks == 1LL) {          if (blocks == 1LL) {
                 warnx("%s: error: no room for the GPT table", device_name);                  gpt_warnx(gpt, "No room for the GPT table");
                 return;                  return -1;
         }          }
   
         blocks--;               /* Number of blocks in the GPT table. */          blocks--;               /* Number of blocks in the GPT table. */
         gpt = map_add(1LL, 1LL, MAP_TYPE_PRI_GPT_HDR, calloc(1, secsz));          gpt->gpt = map_add(gpt, 1LL, 1LL, MAP_TYPE_PRI_GPT_HDR,
         tbl = map_add(2LL, blocks, MAP_TYPE_PRI_GPT_TBL,              calloc(1, gpt->secsz));
             calloc(blocks, secsz));          gpt->tbl = map_add(gpt, 2LL, blocks, MAP_TYPE_PRI_GPT_TBL,
         if (gpt == NULL || tbl == NULL)              calloc(blocks, gpt->secsz));
                 return;          if (gpt->gpt == NULL || gpt->tbl == NULL)
                   return -1;
         lbt = map_add(last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,  
             tbl->map_data);          gpt->lbt = map_add(gpt, last - blocks, blocks, MAP_TYPE_SEC_GPT_TBL,
         tpg = map_add(last, 1LL, MAP_TYPE_SEC_GPT_HDR, calloc(1, secsz));              gpt->tbl->map_data);
           gpt->tpg = map_add(gpt, last, 1LL, MAP_TYPE_SEC_GPT_HDR,
               calloc(1, gpt->secsz));
   
         hdr = gpt->map_data;          hdr = gpt->gpt->map_data;
         memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));          memcpy(hdr->hdr_sig, GPT_HDR_SIG, sizeof(hdr->hdr_sig));
         hdr->hdr_revision = htole32(GPT_HDR_REVISION);          hdr->hdr_revision = htole32(GPT_HDR_REVISION);
   
         /*          /*
          * XXX struct gpt_hdr is not a multiple of 8 bytes in size and thus           * XXX struct gpt_hdr is not a multiple of 8 bytes in size and thus
          * contains padding we must not include in the size.           * contains padding we must not include in the size.
          */           */
         hdr->hdr_size = htole32(GPT_HDR_SIZE);          hdr->hdr_size = htole32(GPT_HDR_SIZE);
         hdr->hdr_lba_self = htole64(gpt->map_start);          hdr->hdr_lba_self = htole64(gpt->gpt->map_start);
         hdr->hdr_lba_alt = htole64(tpg->map_start);          hdr->hdr_lba_alt = htole64(gpt->tpg->map_start);
         hdr->hdr_lba_start = htole64(tbl->map_start + blocks);          hdr->hdr_lba_start = htole64(gpt->tbl->map_start + blocks);
         hdr->hdr_lba_end = htole64(lbt->map_start - 1LL);          hdr->hdr_lba_end = htole64(gpt->lbt->map_start - 1LL);
         gpt_uuid_generate(hdr->hdr_guid);          gpt_uuid_generate(hdr->hdr_guid);
         hdr->hdr_lba_table = htole64(tbl->map_start);          hdr->hdr_lba_table = htole64(gpt->tbl->map_start);
         hdr->hdr_entries = htole32((blocks * secsz) / sizeof(struct gpt_ent));          hdr->hdr_entries = htole32((blocks * gpt->secsz) / sizeof(struct gpt_ent));
         if (le32toh(hdr->hdr_entries) > parts)          if (le32toh(hdr->hdr_entries) > parts)
                 hdr->hdr_entries = htole32(parts);                  hdr->hdr_entries = htole32(parts);
         hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));          hdr->hdr_entsz = htole32(sizeof(struct gpt_ent));
   
         ent = tbl->map_data;          ent = gpt->tbl->map_data;
         for (i = 0; i < le32toh(hdr->hdr_entries); i++) {          for (i = 0; i < le32toh(hdr->hdr_entries); i++) {
                 gpt_uuid_generate(ent[i].ent_guid);                  gpt_uuid_generate(ent[i].ent_guid);
         }          }
Line 366  migrate(int fd)
Line 376  migrate(int fd)
                                 ent->ent_lba_end = htole64(start + size - 1LL);                                  ent->ent_lba_end = htole64(start + size - 1LL);
                                 ent++;                                  ent++;
                         } else                          } else
                                 ent = migrate_disklabel(fd, start, ent);                                  ent = migrate_disklabel(gpt, start, ent);
                         break;                          break;
                 }                  }
                 case MBR_PTYPE_NETBSD:                  case MBR_PTYPE_NETBSD:
                         ent = migrate_netbsd_disklabel(fd, start, ent);                          ent = migrate_netbsd_disklabel(gpt, start, ent);
                         break;                          break;
                 case MBR_PTYPE_EFI: {                  case MBR_PTYPE_EFI: {
                         gpt_uuid_create(GPT_TYPE_EFI,                          gpt_uuid_create(GPT_TYPE_EFI,
Line 383  migrate(int fd)
Line 393  migrate(int fd)
                 }                  }
                 default:                  default:
                         if (!force) {                          if (!force) {
                                 warnx("%s: error: unknown partition type (%d)",                                  gpt_warnx(gpt, "unknown partition type (%d)",
                                     device_name, mbr->mbr_part[i].part_typ);                                      mbr->mbr_part[i].part_typ);
                                 return;                                  return -1;
                         }                          }
                           break;
                 }                  }
         }          }
         ent = tbl->map_data;  
   
         hdr->hdr_crc_table = htole32(crc32(ent, le32toh(hdr->hdr_entries) *          if (gpt_write_primary(gpt) == -1)
             le32toh(hdr->hdr_entsz)));                  return -1;
         hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));  
   
         gpt_write(fd, gpt);  
         gpt_write(fd, tbl);  
   
         /*          /*
          * Create backup GPT.           * Create backup GPT.
          */           */
         memcpy(tpg->map_data, gpt->map_data, secsz);          memcpy(gpt->tpg->map_data, gpt->gpt->map_data, gpt->secsz);
         hdr = tpg->map_data;          hdr = gpt->tpg->map_data;
         hdr->hdr_lba_self = htole64(tpg->map_start);          hdr->hdr_lba_self = htole64(gpt->tpg->map_start);
         hdr->hdr_lba_alt = htole64(gpt->map_start);          hdr->hdr_lba_alt = htole64(gpt->gpt->map_start);
         hdr->hdr_lba_table = htole64(lbt->map_start);          hdr->hdr_lba_table = htole64(gpt->lbt->map_start);
         hdr->hdr_crc_self = 0;                  /* Don't ever forget this! */  
         hdr->hdr_crc_self = htole32(crc32(hdr, le32toh(hdr->hdr_size)));  
   
         gpt_write(fd, lbt);          if (gpt_write_backup(gpt) == -1)
         gpt_write(fd, tpg);                  return -1;
   
         map = map_find(MAP_TYPE_MBR);          map = map_find(gpt, MAP_TYPE_MBR);
         mbr = map->map_data;          mbr = map->map_data;
         /*          /*
          * Turn the MBR into a Protective MBR.           * Turn the MBR into a Protective MBR.
          */           */
         memset(mbr->mbr_part, 0, sizeof(mbr->mbr_part));          memset(mbr->mbr_part, 0, sizeof(mbr->mbr_part));
         mbr->mbr_part[0].part_shd = 0x00;          gpt_create_pmbr_part(mbr->mbr_part, last);
         mbr->mbr_part[0].part_ssect = 0x02;          gpt_write(gpt, map);
         mbr->mbr_part[0].part_scyl = 0x00;          return 0;
         mbr->mbr_part[0].part_typ = MBR_PTYPE_PMBR;  
         mbr->mbr_part[0].part_ehd = 0xfe;  
         mbr->mbr_part[0].part_esect = 0xff;  
         mbr->mbr_part[0].part_ecyl = 0xff;  
         mbr->mbr_part[0].part_start_lo = htole16(1);  
         if (last > 0xffffffff) {  
                 mbr->mbr_part[0].part_size_lo = htole16(0xffff);  
                 mbr->mbr_part[0].part_size_hi = htole16(0xffff);  
         } else {  
                 mbr->mbr_part[0].part_size_lo = htole16(last);  
                 mbr->mbr_part[0].part_size_hi = htole16(last >> 16);  
         }  
         gpt_write(fd, map);  
 }  }
   
 int  int
 cmd_migrate(int argc, char *argv[])  cmd_migrate(gpt_t gpt, int argc, char *argv[])
 {  {
         int ch, fd;          int ch;
   
           parts = 128;
   
         /* Get the migrate options */          /* Get the migrate options */
         while ((ch = getopt(argc, argv, "fs")) != -1) {          while ((ch = getopt(argc, argv, "fp:s")) != -1) {
                 switch(ch) {                  switch(ch) {
                 case 'f':                  case 'f':
                         force = 1;                          force = 1;
                         break;                          break;
                   case 'p':
                           parts = atoi(optarg);
                           break;
                 case 's':                  case 's':
                         slice = 1;                          slice = 1;
                         break;                          break;
                 default:                  default:
                         usage_migrate();                          return usage_migrate();
                 }                  }
         }          }
   
         if (argc == optind)          if (argc != optind)
                 usage_migrate();                  return usage_migrate();
   
         while (optind < argc) {  
                 fd = gpt_open(argv[optind++], 0);  
                 if (fd == -1)  
                         continue;  
   
                 migrate(fd);  
   
                 gpt_close(fd);  
         }  
   
         return (0);          return migrate(gpt);
 }  }

Legend:
Removed from v.1.22  
changed lines
  Added in v.1.23

CVSweb <webmaster@jp.NetBSD.org>