From d52733329923b5379f6a2d6e74a08ac8a7dddf5b Mon Sep 17 00:00:00 2001 From: james Date: Tue, 13 Nov 2007 15:18:30 +0000 Subject: *** empty log message *** --- src/disk.c | 15 ++++- src/gpt.c | 200 ++++++++++++++++++++++++++++++------------------------- src/gpt.h | 1 + src/header.c | 80 ++++++++++++---------- src/modify.c | 44 ++++++------ src/pmbr.c | 60 +++++------------ src/prototypes.h | 4 +- src/show.c | 2 +- src/sync.c | 68 ++++++++++++------- src/util.c | 16 ++--- version-md5sums | 1 + version-micro | 2 +- 12 files changed, 263 insertions(+), 230 deletions(-) diff --git a/src/disk.c b/src/disk.c index 3772862..c9a230f 100644 --- a/src/disk.c +++ b/src/disk.c @@ -1,5 +1,6 @@ #include "project.h" +#include DISK * @@ -45,7 +46,7 @@ disk_read (DISK * d, void *buf, uint64_t lba, int lbas) if (read (d->fd, buf, lbas) != lbas) { perror ("read"); - // abort (); + // abort (); } } void @@ -72,3 +73,15 @@ disk_lbas (DISK * d) { return d->lbas; } + +disk_reread_kernel_table (DISK * d) +{ + if (ioctl (d->fd, BLKRRPART, NULL)) + { + perror ("Telling kernel to re-read partition table failed:"); + } + else + { + fprintf (stderr, "Kernel has re-read partition table\n"); + } +} diff --git a/src/gpt.c b/src/gpt.c index b81964d..7824fef 100644 --- a/src/gpt.c +++ b/src/gpt.c @@ -6,10 +6,13 @@ * */ -static char rcsid[] = "$Id: gpt.c,v 1.12 2007/11/12 13:28:04 james Exp $"; +static char rcsid[] = "$Id: gpt.c,v 1.13 2007/11/13 15:18:30 james Exp $"; /* * $Log: gpt.c,v $ + * Revision 1.13 2007/11/13 15:18:30 james + * *** empty log message *** + * * Revision 1.12 2007/11/12 13:28:04 james * *** empty log message *** * @@ -49,115 +52,130 @@ static char rcsid[] = "$Id: gpt.c,v 1.12 2007/11/12 13:28:04 james Exp $"; #include "project.h" -void usage(void) +void +usage (void) { -fprintf(stderr, -"Usage:\n" -"gpt -h show help\n" -"gpt -d disk-device -l list partitions\n" -"gpt -d disk-device -s print the address of frist usable sector\n" -" on the disk\n" -" the last usable sector on the disk\n" + fprintf (stderr, + "Usage:\n" + "gpt -h show help\n" + "gpt -d disk-device -l list partitions\n" + "gpt -d disk-device -s print the address of frist usable sector\n" + " on the disk\n" + " the last usable sector on the disk\n" #if 0 -"gpt -d disk-device -e print the address of the sector after the\n" -" the last addressable sector on the disk\n" + "gpt -d disk-device -e print the address of the sector after the\n" + " the last addressable sector on the disk\n" #endif -"gpt -d disk-device -e print the address of the last sector\n" -" usable in a partition\n" -"gpt -d disk-device -f n print the lba of the last sector in\n" -" parition n\n" -"gpt -d disk-device -n write a new blank parition table to the disk\n" -" the end of parition n\n" -"gpt -d disk-device -a n name type start end\n" -" set partiton n, type can either be a named\n" -" type or a hexadecimal GUID\n" -"gpt -d disk-device -c fill the PMBR with entries taken from\n" -" the first few GPT entries, using dark\n" -" voodoo\n" -); -exit(1); + "gpt -d disk-device -e print the address of the last sector\n" + " usable in a partition\n" + "gpt -d disk-device -f n print the lba of the last sector in\n" + " parition n\n" + "gpt -d disk-device -n write a new blank parition table to the disk\n" + " the end of parition n\n" + "gpt -d disk-device -a n name type start end\n" + " set partiton n, type can either be a named\n" + " type or a hexadecimal GUID\n" + "gpt -d disk-device -c fill the PMBR with entries taken from\n" + " the first few GPT entries, using dark\n" + " voodoo\n"); + exit (1); } int main (int argc, char *argv[]) { - DISK *d=NULL; + DISK *d = NULL; GPT_headers h; GPT_entry e; int c; int n; - int aflag=0; - uint64_t start_lba,end_lba; + int aflag = 0; + uint64_t start_lba, end_lba; extern char *optarg; extern int optind; - while ((c=getopt(argc,argv,"d:hlsef:unac"))!=EOF) { - switch(c) { - case 'd': - d=disk_open(optarg); - if (!d) { - fprintf(stderr,"failed to open disk %s\n",optarg); - perror("open"); - return -1; - } - break; - case 'e': - if (!d) usage(); - h=headers_get(d); - printf("%lld\n",(long long) h.header.last_usable_lba); - return 0; - case 's': - if (!d) usage(); - h=headers_get(d); - printf("%lld\n",(long long) h.header.first_usable_lba); - return 0; - case 'u': - if (!d) usage(); - h=headers_get(d); - printf("%lld\n",(long long) h.header.last_usable_lba); - return 0; - case 'f': - h=headers_get(d); - n=atoi(optarg); - e=entry_read(d,&h.header,n); - printf("%lld\n",e.end); - return 0; - case 'n': - if (!d) usage(); - new(d); - return 0; - case 'a': - aflag++; - break; - case 'l': - if (!d) usage(); - show(d); - return 0; - case 'c': - if (!d) usage(); - sync_tables(d); - //show(d); - return 0; - default: - usage(); - } -} - - if (!aflag) usage(); -if (!d) usage(); - -if ((argc-optind)!=5) usage(); - -start_lba=strtoll(argv[optind+3],NULL,0); -end_lba=strtoll(argv[optind+4],NULL,0); + while ((c = getopt (argc, argv, "d:hlsef:unac")) != EOF) + { + switch (c) + { + case 'd': + d = disk_open (optarg); + if (!d) + { + fprintf (stderr, "failed to open disk %s\n", optarg); + perror ("open"); + return -1; + } + break; + case 'e': + if (!d) + usage (); + h = headers_get (d); + printf ("%lld\n", (long long) h.header.last_usable_lba); + return 0; + case 's': + if (!d) + usage (); + h = headers_get (d); + printf ("%lld\n", (long long) h.header.first_usable_lba); + return 0; + case 'u': + if (!d) + usage (); + h = headers_get (d); + printf ("%lld\n", (long long) h.header.last_usable_lba); + return 0; + case 'f': + h = headers_get (d); + n = atoi (optarg); + e = entry_read (d, &h.header, n); + printf ("%lld\n", e.end); + return 0; + case 'n': + if (!d) + usage (); + new (d); + disk_reread_kernel_table (d); + return 0; + case 'a': + aflag++; + break; + case 'l': + if (!d) + usage (); + show (d); + return 0; + case 'c': + if (!d) + usage (); + sync_tables (d); + show (d); + disk_reread_kernel_table (d); + return 0; + default: + usage (); + } + } + + if (!aflag) + usage (); + if (!d) + usage (); + + if ((argc - optind) != 5) + usage (); + + start_lba = strtoll (argv[optind + 3], NULL, 0); + end_lba = strtoll (argv[optind + 4], NULL, 0); //printf("%lld %lld\n",(long long)start_lba,(long long) end_lba); -n=atoi(argv[optind]); + n = atoi (argv[optind]); -modify(d,n,argv[optind+1] ,argv[optind+2],start_lba,end_lba); + modify (d, n, argv[optind + 1], argv[optind + 2], start_lba, end_lba); -show(d); -return 0; + show (d); + disk_reread_kernel_table (d); + return 0; } diff --git a/src/gpt.h b/src/gpt.h index 16711df..dff9dc4 100644 --- a/src/gpt.h +++ b/src/gpt.h @@ -51,6 +51,7 @@ typedef struct #define MBR_PARTITION_TYPE_EFI 0xee #define MBR_PARTITION_TYPE_LINUX 0x83 #define MBR_PARTITION_TYPE_SWAP 0x82 +#define MBR_PARTITION_TYPE_HFS 0xaf #define MBR_PARTITION_TYPE_UNKOWN 0xff #define MBR_PARTITION_BOOTABLE 0x80 diff --git a/src/header.c b/src/header.c index 6c3133d..81caf29 100644 --- a/src/header.c +++ b/src/header.c @@ -117,75 +117,81 @@ header_show (DISK * d, GPT_header * h) } -int header_validate(DISK *d,GPT_header *h) +int +header_validate (DISK * d, GPT_header * h) { GPT_header c = *h; -uint32_t crc; + uint32_t crc; c.header_crc = 0; -if (memcmp (h->signature, GPT_HEADER_SIGNATURE, sizeof (h->signature))) - return 0; + if (memcmp (h->signature, GPT_HEADER_SIGNATURE, sizeof (h->signature))) + return 0; crc = crc32 (0, &c, sizeof (c)); - if (crc != h->header_crc) return 0; + if (crc != h->header_crc) + return 0; crc = header_calc_ent_crc (d, h); -if (crc == h->partition_entry_crc) return 0; + if (crc == h->partition_entry_crc) + return 0; -return 1; + return 1; } -void header_redo_ent_crc(DISK *d,GPT_header *h) +void +header_redo_ent_crc (DISK * d, GPT_header * h) { -h->partition_entry_crc=header_calc_ent_crc(d,h); -h->header_crc=0; -h->header_crc=crc32(0,h,sizeof(*h)); + h->partition_entry_crc = header_calc_ent_crc (d, h); + h->header_crc = 0; + h->header_crc = crc32 (0, h, sizeof (*h)); } -void header_write(DISK *d,GPT_header *h) + +void +header_write (DISK * d, GPT_header * h) { -uint8_t buf[512]; -memcpy(buf,h,sizeof(*h)); + uint8_t buf[512]; + memcpy (buf, h, sizeof (*h)); -printf("Writing header to lba %lld\n",(long long) h->my_lba); -disk_write(d,buf,h->my_lba,1); + printf ("Writing header to lba %lld\n", (long long) h->my_lba); + disk_write (d, buf, h->my_lba, 1); } -int headers_validate(DISK *d,GPT_headers *h) +int +headers_validate (DISK * d, GPT_headers * h) { -if (!header_validate(d,&h->header)) return 0; -return header_validate(d,&h->alt_header); + if (!header_validate (d, &h->header)) + return 0; + return header_validate (d, &h->alt_header); } -GPT_headers headers_get(DISK *d) +GPT_headers +headers_get (DISK * d) { -GPT_headers ret; -uint8_t buf[512]; -uint64_t lbas; + GPT_headers ret; + uint8_t buf[512]; + uint64_t lbas; -lbas=disk_lbas(d); + lbas = disk_lbas (d); -disk_read(d,buf,1,1); -memcpy(&ret.header,buf,sizeof(ret.header)); + disk_read (d, buf, 1, 1); + memcpy (&ret.header, buf, sizeof (ret.header)); -lbas--; + lbas--; -if (lbas!=ret.header.alternate_lba) { - fprintf(stderr,"WARNING: alternate lba is not at end of disk\n"); -} + if (lbas != ret.header.alternate_lba) + { + fprintf (stderr, "WARNING: alternate lba is not at end of disk\n"); + } -disk_read(d,buf,ret.header.alternate_lba,1); -memcpy(&ret.alt_header,buf,sizeof(ret.alt_header)); + disk_read (d, buf, ret.header.alternate_lba, 1); + memcpy (&ret.alt_header, buf, sizeof (ret.alt_header)); -return ret; + return ret; } - - - - diff --git a/src/modify.c b/src/modify.c index 89500ac..3632ec7 100644 --- a/src/modify.c +++ b/src/modify.c @@ -3,36 +3,38 @@ int -modify (DISK * d, int n, char *name,char *type_guid, uint64_t start, uint64_t end) +modify (DISK * d, int n, char *name, char *type_guid, uint64_t start, + uint64_t end) { GPT_headers h; - GPT_entry e={0}; + GPT_entry e = { 0 }; - h=headers_get(d); + h = headers_get (d); - if(a_to_guid(type_guid,&e.type)) { - fprintf(stderr,"GUID type %s was not parsed\n",type_guid); - exit(1); - } - printf("guid=%s became=%s\n",type_guid,guid_to_a(e.type)); - e.label=guid_random(); - e.start=start; - e.end=end; - + if (a_to_guid (type_guid, &e.type)) + { + fprintf (stderr, "GUID type %s was not parsed\n", type_guid); + exit (1); + } + printf ("guid=%s became=%s\n", type_guid, guid_to_a (e.type)); + e.label = guid_random (); + e.start = start; + e.end = end; - ascii_to_utf16(name,-1,e.name,sizeof(e.name)); + ascii_to_utf16 (name, -1, e.name, sizeof (e.name)); - entry_show(&e); + + entry_show (&e); /*Odd order because efi says so*/ - entry_write(d,&h.header,n,&e); - header_redo_ent_crc(d,&h.header); - header_write(d,&h.header); + entry_write (d, &h.header, n, &e); + header_redo_ent_crc (d, &h.header); + header_write (d, &h.header); - entry_write(d,&h.alt_header,n,&e); - header_redo_ent_crc(d,&h.alt_header); - header_write(d,&h.alt_header); -return 0; + entry_write (d, &h.alt_header, n, &e); + header_redo_ent_crc (d, &h.alt_header); + header_write (d, &h.alt_header); + return 0; } diff --git a/src/pmbr.c b/src/pmbr.c index a958f83..b110850 100644 --- a/src/pmbr.c +++ b/src/pmbr.c @@ -12,7 +12,8 @@ mbr_entry_show (MBR_entry * e) printf (" system %02x end chs %5d/%3d/%2d end sector %10d\n", e->system, MBR_CYLINDER (e->chs_end.cs), - e->chs_end.head, MBR_SECTOR (e->chs_end.cs), e->size + e->start); + e->chs_end.head, MBR_SECTOR (e->chs_end.cs), + e->size + e->start - 1); } void @@ -93,26 +94,23 @@ sector_to_chs (uint32_t lba) return ret; } -void -mbr_set_entry0_from_gpt_header (MBR_entry * m, GPT_header * h) +static CHS +invalid_chs (void) { - MBR ret = { 0 }; - uint32_t start = 1; - uint32_t end = h->first_usable_lba - 1; + CHS ret; + + ret.head = 254; + ret.cs = MBR_CS (1023, 63); + return ret; +} + - m->bootable = 0; - m->chs_start = sector_to_chs (start); - m->system = MBR_PARTITION_TYPE_EFI; - m->chs_end = sector_to_chs (end); - m->start = start; - m->size = (end - start) + 1; -} void -mbr_entry_from_gpt_entry (MBR_entry * m, GPT_entry * g, int bootable, - uint8_t type) +mbr_entry_from_gpt_entry (MBR_entry * m, GPT_header * h, GPT_entry * g, + int bootable, uint8_t type) { MBR ret = { 0 }; uint32_t start = g->start; @@ -121,37 +119,15 @@ mbr_entry_from_gpt_entry (MBR_entry * m, GPT_entry * g, int bootable, m->system = type; m->bootable = bootable ? MBR_PARTITION_BOOTABLE : 0x00; - m->chs_start = sector_to_chs (start); - m->chs_end = sector_to_chs (end); + m->chs_start = invalid_chs (); + m->chs_end = invalid_chs (); m->start = start; m->size = (end - start) + 1; -} -void -mbr_wedge_entry (MBR_entry * m) -{ - MBR ret = { 0 }; - - int c = MBR_CYLINDER (m->chs_end.cs); - int s = MBR_SECTOR (m->chs_end.cs); - int h = m->chs_end.head; - - while ((s != 63) || (h != 254)) + if (type == MBR_PARTITION_TYPE_EFI) { - s++; - if (s == 64) - { - s = 1; - h++; - if (h == 255) - { - c++; - h = 0; - } - } - m->size++; + m->size += m->start -1; + m->start = 1; } - m->chs_end.head = h; - m->chs_end.cs = MBR_CS (c, s); } diff --git a/src/prototypes.h b/src/prototypes.h index 201f984..3b9bb81 100644 --- a/src/prototypes.h +++ b/src/prototypes.h @@ -32,9 +32,7 @@ uint64_t disk_lbas(DISK *d); void mbr_entry_show(MBR_entry *e); void mbr_show(MBR *m); MBR mbr_new(uint64_t lbas); -void mbr_set_entry0_from_gpt_header(MBR_entry *m, GPT_header *h); -void mbr_entry_from_gpt_entry(MBR_entry *m, GPT_entry *g, int bootable, uint8_t type); -void mbr_wedge_entry(MBR_entry *m); +void mbr_entry_from_gpt_entry(MBR_entry *m, GPT_header *h, GPT_entry *g, int bootable, uint8_t type); /* show.c */ void show(DISK *d); /* entry.c */ diff --git a/src/show.c b/src/show.c index 20decd1..aa1123a 100644 --- a/src/show.c +++ b/src/show.c @@ -15,7 +15,7 @@ show (DISK * d) m = (MBR *) buf; mbr_show (m); - h=headers_get(d); + h = headers_get (d); header_show (d, &h.header); header_show (d, &h.alt_header); diff --git a/src/sync.c b/src/sync.c index 1b0638b..38bb84f 100644 --- a/src/sync.c +++ b/src/sync.c @@ -8,37 +8,59 @@ sync_tables (DISK * d) uint8_t mbuf[512]; GPT_headers h; int i; - GUID guid_ext3=GUID_TYPE_LINUX_EXT3; - GUID guid_swap=GUID_TYPE_LINUX_SWAP; - int me=0; + GUID guid_ext3 = GUID_TYPE_LINUX_EXT3; + GUID guid_swap = GUID_TYPE_LINUX_SWAP; + GUID guid_hfs = GUID_TYPE_APPLE_HFS; + GUID guid_efi = GUID_TYPE_SYSTEM; + int mbr_entry = 0; + int seen_linux = 0; disk_read (d, mbuf, 0, 1); m = (MBR *) mbuf; - h=headers_get(d); - - mbr_set_entry0_from_gpt_header(&m->entry[me++],&h.header); + h = headers_get (d); for (i = 0; i < h.header.n_partition_entries; ++i) { - GPT_entry e = entry_read (d, &h.header, i); - if (!guid_cmp(&e.type,&guid_swap)) { - mbr_entry_from_gpt_entry (&m->entry[me++],&e,(me==1),MBR_PARTITION_TYPE_LINUX); - } else if (!guid_cmp(&e.type,&guid_ext3)) { - mbr_entry_from_gpt_entry (&m->entry[me++],&e,(me==1),MBR_PARTITION_TYPE_SWAP); - - - } - if (me==4) break; - } - - for (i=0;ientry[i].system==MBR_PARTITION_TYPE_SWAP) || (i==(me-1))) { - mbr_wedge_entry(&m->entry[i]); - break; - } - } + GPT_entry e = entry_read (d, &h.header, i); + uint8_t type = 0, bootable = 0; + + if (!guid_cmp (&e.type, &guid_efi)) + { + type = MBR_PARTITION_TYPE_EFI; + } + else if (!guid_cmp (&e.type, &guid_ext3)) + { + type = MBR_PARTITION_TYPE_LINUX; + } + else if (!guid_cmp (&e.type, &guid_swap)) + { + type = MBR_PARTITION_TYPE_SWAP; + } + else if (!guid_cmp (&e.type, &guid_hfs)) + { + type = MBR_PARTITION_TYPE_HFS; + } + + if ((type == MBR_PARTITION_TYPE_LINUX) && (!seen_linux)) + { + seen_linux++; + bootable++; + } + + mbr_entry_from_gpt_entry (&m->entry[mbr_entry++], &h.header, &e, + bootable, type); + + if (mbr_entry == 4) + break; + } + + for (; mbr_entry < 4; ++mbr_entry) + { + memset (&m->entry[mbr_entry], 0, sizeof (MBR_entry)); + } + disk_write (d, mbuf, 0, 1); diff --git a/src/util.c b/src/util.c index f59ccb9..1356fd9 100644 --- a/src/util.c +++ b/src/util.c @@ -53,10 +53,10 @@ hexdump (FILE * f, uint8_t * data, int s, int l) } void -utf16_to_ascii (void * _u16, int u16_len, void * _u8, int u8_len) +utf16_to_ascii (void *_u16, int u16_len, void *_u8, int u8_len) { - uint16_t *u16=(uint16_t *) _u16; - uint8_t *u8=(uint8_t *) _u8; + uint16_t *u16 = (uint16_t *) _u16; + uint8_t *u8 = (uint8_t *) _u8; u16_len >>= 1; @@ -83,10 +83,10 @@ utf16_to_ascii (void * _u16, int u16_len, void * _u8, int u8_len) } void -ascii_to_utf16 (void * _u8, int u8_len, void * _u16, int u16_len) +ascii_to_utf16 (void *_u8, int u8_len, void *_u16, int u16_len) { - uint16_t *u16=(uint16_t *) _u16; - uint8_t *u8=(uint8_t *) _u8; + uint16_t *u16 = (uint16_t *) _u16; + uint8_t *u8 = (uint8_t *) _u8; u16_len >>= 1; @@ -111,7 +111,3 @@ ascii_to_utf16 (void * _u8, int u8_len, void * _u16, int u16_len) *u16 = 0; return; } - - - - diff --git a/version-md5sums b/version-md5sums index b65eb1e..fe0bab8 100644 --- a/version-md5sums +++ b/version-md5sums @@ -1 +1,2 @@ 745c00d2207e046f159b63dffbfbe491 1.0.1 +95b82ac0870dc040a8a810114160e7c7 1.0.2 diff --git a/version-micro b/version-micro index d00491f..0cfbf08 100644 --- a/version-micro +++ b/version-micro @@ -1 +1 @@ -1 +2 -- cgit v1.2.3