aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root>2007-09-09 22:29:50 +0000
committerroot <root>2007-09-09 22:29:50 +0000
commita501062f338339d1dbafebc55841cbdc570a27b6 (patch)
tree4f314db4049d665fc3a0acacbbbec4ee803159e6
parentb013532b3061cc661ee9d0b141efbc86cda5c320 (diff)
downloadgpt-a501062f338339d1dbafebc55841cbdc570a27b6.tar.gz
gpt-a501062f338339d1dbafebc55841cbdc570a27b6.tar.bz2
gpt-a501062f338339d1dbafebc55841cbdc570a27b6.zip
*** empty log message ***
-rw-r--r--src/add.c21
-rw-r--r--src/disk.c73
-rw-r--r--src/disk.h6
-rw-r--r--src/entry.c40
-rw-r--r--src/gpt.c41
-rw-r--r--src/guid.c130
-rw-r--r--src/header.c137
-rw-r--r--src/new.c47
-rw-r--r--src/pmbr.c58
-rw-r--r--src/prototypes.h30
-rw-r--r--src/show.c31
-rw-r--r--src/util.c21
12 files changed, 521 insertions, 114 deletions
diff --git a/src/add.c b/src/add.c
new file mode 100644
index 0000000..fb6bf25
--- /dev/null
+++ b/src/add.c
@@ -0,0 +1,21 @@
+#include "project.h"
+
+
+
+void add(DISK *d,int n,char *guid,int start,int end)
+{
+GPT_header *h;
+GPT_entry *e;
+
+uint8_t buf[512];
+
+disk_read(d,buf,1,1);
+h=(GPT_header *)buf;
+
+}
+
+
+
+
+
+
diff --git a/src/disk.c b/src/disk.c
new file mode 100644
index 0000000..8ccaf8e
--- /dev/null
+++ b/src/disk.c
@@ -0,0 +1,73 @@
+
+#include "project.h"
+
+
+DISK *
+disk_open (char *fn)
+{
+ DISK *ret = calloc (1, sizeof (DISK));
+ off_t o;
+
+ ret->fd = open (fn, O_RDWR);
+
+ if (ret->fd < 0)
+ {
+ free (ret);
+ return NULL;
+ }
+
+
+ ret->name = strdup (fn);
+
+ ret->lbas = lseek (ret->fd, (off_t) 0, SEEK_END);
+
+
+ ret->lbas = ret->lbas / (uint64_t) SECTOR_SIZE;
+
+ fprintf (stderr, "Opened %s with size of %d lbas\n", ret->name,
+ (int) ret->lbas);
+
+ return ret;
+}
+
+void
+disk_read (DISK * d, void *buf, uint64_t lba, int lbas)
+{
+ lba *= SECTOR_SIZE;
+
+ if (lseek (d->fd, lba, SEEK_SET) != lba)
+ {
+ perror ("lseek");
+ abort ();
+ }
+
+ lbas *= SECTOR_SIZE;
+ if (read (d->fd, buf, lbas) != lbas)
+ {
+ perror ("read");
+ abort ();
+ }
+}
+void
+disk_write (DISK * d, void *buf, uint64_t lba, int lbas)
+{
+ lba *= SECTOR_SIZE;
+
+ if (lseek (d->fd, lba, SEEK_SET) != lba)
+ {
+ perror ("lseek");
+ abort ();
+ }
+
+ lbas *= SECTOR_SIZE;
+ if (write (d->fd, buf, lbas) != lbas)
+ {
+ perror ("write");
+ abort ();
+ }
+}
+
+uint64_t disk_lbas(DISK *d)
+{
+return d->lbas;
+}
diff --git a/src/disk.h b/src/disk.h
new file mode 100644
index 0000000..468813a
--- /dev/null
+++ b/src/disk.h
@@ -0,0 +1,6 @@
+
+typedef struct {
+ char *name;
+ int fd;
+ uint64_t lbas;
+} DISK;
diff --git a/src/entry.c b/src/entry.c
new file mode 100644
index 0000000..2044813
--- /dev/null
+++ b/src/entry.c
@@ -0,0 +1,40 @@
+#include "project.h"
+
+void entry_write(DISK *d,GPT_header *h,int n,GPT_entry *e)
+{
+uint8_t buf[SECTOR_SIZE];
+uint64_t lba=GPT_ENTRY_LBA (h, n);
+
+disk_read (d, buf, lba,1);
+memcpy(&buf[GPT_ENTRY_OFFSET(h,n)],e,sizeof(*e));
+disk_write (d, buf, lba, 1);
+}
+
+GPT_entry entry_read(DISK *d,GPT_header *h,int n)
+{
+uint8_t buf[SECTOR_SIZE];
+GPT_entry e;
+
+disk_read (d, buf, GPT_ENTRY_LBA (h, n), 1);
+memcpy(&e,&buf[GPT_ENTRY_OFFSET(h,n)],sizeof(e));
+return e;
+}
+
+
+int entry_empty(GPT_entry *e) {
+GUID empty=GUID_TYPE_EMPTY;
+return !guid_cmp(&e->type,&empty);
+}
+
+void entry_show(GPT_entry *e)
+{
+char name[sizeof(e->name)+1];
+
+utf16_to_ascii(e->name,sizeof(e->name),name,sizeof(name));
+
+
+printf(" Name %s\n",name);
+printf(" Flags %16x Label %s\n",(int) e->flags,guid_to_a(e->label));
+printf(" Start %10lld End %10lld Type %s\n",(long long) e->start,(long long) e->end,guid_to_a(e->type));
+
+}
diff --git a/src/gpt.c b/src/gpt.c
index c0f4bf5..2084fca 100644
--- a/src/gpt.c
+++ b/src/gpt.c
@@ -6,10 +6,13 @@
*
*/
-static char rcsid[] = "$Id: gpt.c,v 1.2 2007/09/08 18:21:23 root Exp $";
+static char rcsid[] = "$Id: gpt.c,v 1.3 2007/09/09 22:29:50 root Exp $";
/*
* $Log: gpt.c,v $
+ * Revision 1.3 2007/09/09 22:29:50 root
+ * *** empty log message ***
+ *
* Revision 1.2 2007/09/08 18:21:23 root
* *** empty log message ***
*
@@ -26,34 +29,34 @@ static char rcsid[] = "$Id: gpt.c,v 1.2 2007/09/08 18:21:23 root Exp $";
int
main (int argc, char *argv[])
{
-int fd;
-char buf[512];
-GPT_entry *e;
-GPT_header *h;
-int i,j;
+ DISK *d;
-fd=open("/dev/sda",O_RDONLY);
+ d = disk_open ("/dev/sdb");
-read(fd,buf,512);
-read(fd,buf,512);
-h=(GPT_header *) buf;
+ //new(d);
+ add(d,1,"linux-ext3",10*1024*2,30*1024*2);
+ show(d);
-header_print(h);
+#if 0
+ printf ("hecrc=%08x\n", header_calc_ent_crc (d, h));
+
+
+ return 0;
-for (i=0;i<2;++i) {
-read(fd,buf,512);
//hexdump(stderr,buf,0,512);
-for (j=0;j<4;++j) {
-e=(GPT_entry *) buf;
-e+=j;
-printf("%d,%d: %s\n",i,j,guid_to_a(e->type));
-}
+ for (j = 0; j < 4; ++j)
+ {
+ e = (GPT_entry *) buf;
+ e += j;
+ printf ("%d,%d: %s\n", i, j, guid_to_a (e->type));
+ }
}
- return 0;
+#endif
+return 0;
}
diff --git a/src/guid.c b/src/guid.c
index d9d5dcb..006c4e2 100644
--- a/src/guid.c
+++ b/src/guid.c
@@ -9,16 +9,18 @@ static struct known_struct
{
{ GUID_TYPE_EMPTY, "empty"},
{ GUID_TYPE_SYSTEM, "EFI SYSTEM"},
-{GUID_TYPE_LINUX_EXT3,"linux-ext3"},
-{GUID_TYPE_LINUX_SWAP,"linux-swap"},
-{GUID_TYPE_APPLE_HFS,"apple-hfs"},
- { {0}, NULL}
+ { GUID_TYPE_LINUX_EXT3, "linux-ext3"},
+ { GUID_TYPE_LINUX_SWAP, "linux-swap"},
+ { GUID_TYPE_APPLE_HFS, "apple-hfs"},
+ { GUID_TYPE_APPLE_TV, "apple-tv"},
+ { { 0}, NULL}
};
-int guid_cmp(GUID *a,GUID *b)
+int
+guid_cmp (GUID * a, GUID * b)
{
-return memcmp(a,b,sizeof(GUID));
+ return memcmp (a, b, sizeof (GUID));
}
#define GUIDTOARETSIZE 80
@@ -49,74 +51,78 @@ guid_to_a (GUID g)
}
int
-a_to_guid (char *a,GUID *g)
+a_to_guid (char *a, GUID * g)
{
struct known_struct *ptr = known_guids;
- int digit[32],ndigits=0,i;
+ int digit[32], ndigits = 0, i;
while (ptr->name)
{
if (!strcmp (a, ptr->name))
- memcpy(g,&ptr->g,sizeof(GUID));
- return 0;
+ memcpy (g, &ptr->g, sizeof (GUID));
+ return 0;
}
- while ((*a) && (ndigits!=32)) {
- switch (*a) {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case '-':
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- digit[ndigits++]=(*a)-'0';
- break;
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- digit[ndigits++]=((*a)-'A')+0xA;
- break;
-
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- digit[ndigits++]=((*a)-'a')+0xa;
- break;
- defalt:
- return -1;
- }
- }
-
-for (i=0;i<16;++i) {
- g->d[i]=(digit[(i<<1)] << 4) | digit[(i<<1)+1];
-}
+ while ((*a) && (ndigits != 32))
+ {
+ switch (*a)
+ {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '-':
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ digit[ndigits++] = (*a) - '0';
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ digit[ndigits++] = ((*a) - 'A') + 0xA;
+ break;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ digit[ndigits++] = ((*a) - 'a') + 0xa;
+ break;
+ defalt:
+ return -1;
+ }
+ }
+
+ for (i = 0; i < 16; ++i)
+ {
+ g->d[i] = (digit[(i << 1)] << 4) | digit[(i << 1) + 1];
+ }
return 0;
}
-
-GUID random_guid(void)
+
+GUID
+guid_random (void)
{
-GUID ret;
+ GUID ret;
-int fd=open("/dev/random",O_RDONLY);
-read(fd,&ret,sizeof(ret));
-close(fd);
-return ret;
+ int fd = open ("/dev/random", O_RDONLY);
+ read (fd, &ret, sizeof (ret));
+ close (fd);
+ return ret;
}
diff --git a/src/header.c b/src/header.c
index d577837..e92fd5d 100644
--- a/src/header.c
+++ b/src/header.c
@@ -1,36 +1,113 @@
#include "project.h"
-void header_print(uint8_t *buf)
+
+#define TABLE_SIZE (((sizeof(GPT_entry)*GPT_PARITION_ENTRIES)/SECTOR_SIZE)+2)
+
+void
+header_calc_crc (GPT_header * h)
{
-GPT_header *h=(GPT_header *) buf;
-
-
-printf ("Signature %c%c%c%c%c%c%c%c\n",
- h->signature[0],
- h->signature[1],
- h->signature[2],
- h->signature[3],
- h->signature[4],
- h->signature[5],
- h->signature[6],
- h->signature[7]);
-
-printf("rev=0x%08x header_size=%d header_crc=0x%08x\n",
- h->revision,h->header_size,h->header_crc);
-printf("my_lba=%lld alternate_lba=%lld first_lba=%lld last_lba=%lld\n",
- (long long) h->my_lba, (long long) h->alternate_lba,
- (long long) h->first_usable_lba,(long long) h->last_usable_lba);
-
-printf("guid=%s\n",guid_to_a(h->disk_guid));
-printf("partition_entry_lba=%lld n_entries=%d ent_size=%d ents_crc=%08x\n",
- (long long) h->partition_entry_lba, h->n_partition_entries,
- h->partition_entry_size,h->partition_entry_crc);
-
-printf("%x\n",crc32(0,buf,92));
-h->header_crc=0;
-printf("%x\n",crc32(0,buf,92));
-h->partition_entry_crc=0;
-printf("%x\n",crc32(0,buf,92));
+
+ h->header_crc = 0;
+ h->header_crc = crc32 (0, h, sizeof (GPT_header));
}
+GPT_header
+header_new (GUID disk_guid, int lbas, int alt)
+{
+ GPT_header ret = { 0 };
+
+ memcpy (ret.signature, GPT_HEADER_SIGNATURE, sizeof (ret.signature));
+ ret.revision = GPT_HEADER_REVISION_EFI10;
+ ret.header_size = sizeof (GPT_header);
+
+ ret.first_usable_lba = TABLE_SIZE;
+ ret.last_usable_lba = lbas - TABLE_SIZE;
+
+ ret.n_partition_entries = GPT_PARITION_ENTRIES;
+ ret.partition_entry_size = sizeof (GPT_entry);
+
+ ret.disk_guid = disk_guid;
+
+ if (!alt)
+ {
+ ret.my_lba = 1;
+ ret.alternate_lba = lbas - 1;
+ ret.partition_entry_lba = 2;
+ }
+ else
+ {
+ ret.my_lba = lbas - 1;
+ ret.alternate_lba = 1;
+ ret.partition_entry_lba = lbas - TABLE_SIZE;
+ }
+
+ header_calc_crc (&ret);
+
+ return ret;
+}
+
+
+
+uint32_t
+header_calc_ent_crc (DISK * d, GPT_header * h)
+{
+ int i;
+ GPT_entry e;
+ uint32_t crc = 0;
+
+
+ for (i = 0; i < h->n_partition_entries; ++i)
+ {
+ e=entry_read(d,h,i);
+ crc = crc32 (crc, &e, h->partition_entry_size);
+ }
+
+ return crc;
+}
+
+
+void
+header_show (DISK *d,GPT_header *h)
+{
+ GPT_header c=*h;
+ uint32_t crc;
+ int i;
+
+ if (h->my_lba<h->alternate_lba) {
+ printf(" GPT:\n");
+ } else {
+ printf(" ALTERNATE GPT:\n");
+ }
+
+ c.header_crc=0;
+ crc=crc32(0,&c,sizeof(c));
+
+ printf(" Signature %s, CRC %s\n",
+ (memcmp(h->signature, GPT_HEADER_SIGNATURE,sizeof(h->signature))) ? "INVALID":"valid",
+ (crc==h->header_crc) ?"matches":"DOES NOT MATCH");
+
+ printf (" rev=0x%08x lba=%lld alternate=%lld\n",
+ h->revision,
+ (long long) h->my_lba, (long long) h->alternate_lba);
+ printf (" usable lbas %lld-%lld\n",
+ (long long) h->first_usable_lba, (long long) h->last_usable_lba);
+
+ printf (" DISK GUID: %s\n", guid_to_a (h->disk_guid));
+
+
+ crc=header_calc_ent_crc(d,h);
+
+ printf (" patitions (at lba %lld) CRC %s:\n",
+ (long long) h->partition_entry_lba,
+ (crc == h->partition_entry_crc) ? "matches":"DOES NOT MATCH");
+
+ for (i=0;i<h->n_partition_entries;++i) {
+ GPT_entry e=entry_read(d,h,i);
+ if (!entry_empty(&e)) {
+ printf(" %d:\n",i);
+ entry_show(&e);
+ }
+ }
+
+}
diff --git a/src/new.c b/src/new.c
new file mode 100644
index 0000000..d8c177f
--- /dev/null
+++ b/src/new.c
@@ -0,0 +1,47 @@
+#include "project.h"
+
+
+
+
+void new(DISK *d)
+{
+uint8_t buf[SECTOR_SIZE];
+
+MBR m;
+GPT_header h,alt_h;
+GPT_entry e={0};
+GUID disk_guid;
+uint64_t lbas;
+int n;
+
+lbas=disk_lbas(d);
+
+
+disk_guid=guid_random();
+
+m=mbr_new(lbas);
+memcpy(buf,&m,sizeof(m));
+disk_write(d,buf,0,1);
+
+h=header_new ( disk_guid, lbas,0);
+alt_h=header_new(disk_guid,lbas,1);
+
+for (n=0;n<h.n_partition_entries;++n) {
+entry_write(d,&h,n,&e);
+entry_write(d,&alt_h,n,&e);
+}
+
+h.partition_entry_crc=header_calc_ent_crc(d,&h);
+alt_h.partition_entry_crc=header_calc_ent_crc(d,&alt_h);
+
+header_calc_crc(&h);
+header_calc_crc(&alt_h);
+
+memcpy(buf,&h,sizeof(h));
+disk_write(d,buf,h.my_lba,1);
+
+memcpy(buf,&alt_h,sizeof(alt_h));
+disk_write(d,buf,alt_h.my_lba,1);
+
+}
+
diff --git a/src/pmbr.c b/src/pmbr.c
new file mode 100644
index 0000000..0ba1752
--- /dev/null
+++ b/src/pmbr.c
@@ -0,0 +1,58 @@
+#include "project.h"
+
+
+void mbr_entry_show(MBR_entry *e)
+{
+printf(" flags %02x start chs %5d/%3d/%2d start sector %10d\n",
+ e->bootable,
+ MBR_CYLINDER(e->chs_start.cs),
+ e->chs_start.head,
+ MBR_SECTOR(e->chs_start.cs),
+ e->start);
+
+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);
+}
+void mbr_show(MBR *m)
+{
+int i;
+
+printf(" PMBR:\n");
+
+for (i=0;i<4;++i) {
+if (m->entry[i].system) {
+printf(" Entry %d:\n",i);
+mbr_entry_show(&m->entry[i]);
+}
+}
+if (memcmp(m->signature,MBR_SIGNATURE,sizeof(m->signature))) {
+printf(" Signature INVALID\n");
+} else {
+printf(" Signature valid\n");
+}
+}
+
+MBR mbr_new(uint64_t lbas)
+{
+uint64_t cyls=lbas;
+MBR ret={0};
+
+cyls=cyls/(63*255);
+if (cyls>1023) cyls=1023;
+
+ret.entry[0].bootable=0;
+ret.entry[0].chs_start.cs=MBR_CS(0,1);
+ret.entry[0].system=MBR_PARTITION_TYPE_EFI;
+ret.entry[0].chs_end.head=254;
+ret.entry[0].chs_end.cs=MBR_CS(cyls,63);
+ret.entry[0].start=1;
+ret.entry[0].size=lbas-1;
+
+memcpy(ret.signature,MBR_SIGNATURE,sizeof(ret.signature));
+
+return ret;
+}
diff --git a/src/prototypes.h b/src/prototypes.h
index a3f15d4..630e5c0 100644
--- a/src/prototypes.h
+++ b/src/prototypes.h
@@ -3,12 +3,36 @@ int main(int argc, char *argv[]);
/* version.c */
/* util.c */
void hexdump(FILE *f, uint8_t *data, int s, int l);
+void utf16_to_ascii(uint16_t *u16, int u16_len, uint8_t *u8, int u8_len);
/* guid.c */
int guid_cmp(GUID *a, GUID *b);
char *guid_to_a(GUID g);
int a_to_guid(char *a, GUID *g);
-GUID random_guid(void);
+GUID guid_random(void);
/* crc.c */
-uint32_t crc32(uint32_t crc, const uint8_t *buf, int len);
+uint32_t crc32(uint32_t crc, const void *_buf, int len);
/* header.c */
-void header_print(uint8_t *buf);
+void header_calc_crc(GPT_header *h);
+GPT_header header_new(GUID disk_guid, int lbas, int alt);
+uint32_t header_calc_ent_crc(DISK *d, GPT_header *h);
+void header_show(DISK *d, GPT_header *h);
+/* disk.c */
+DISK *disk_open(char *fn);
+void disk_read(DISK *d, void *buf, uint64_t lba, int lbas);
+void disk_write(DISK *d, void *buf, uint64_t lba, int lbas);
+uint64_t disk_lbas(DISK *d);
+/* pmbr.c */
+void mbr_entry_show(MBR_entry *e);
+void mbr_show(MBR *m);
+MBR mbr_new(uint64_t lbas);
+/* show.c */
+void show(DISK *d);
+/* entry.c */
+void entry_write(DISK *d, GPT_header *h, int n, GPT_entry *e);
+GPT_entry entry_read(DISK *d, GPT_header *h, int n);
+int entry_empty(GPT_entry *e);
+void entry_show(GPT_entry *e);
+/* new.c */
+void new(DISK *d);
+/* add.c */
+void add(DISK *d, int n, char *guid, int start, int end);
diff --git a/src/show.c b/src/show.c
new file mode 100644
index 0000000..6297c85
--- /dev/null
+++ b/src/show.c
@@ -0,0 +1,31 @@
+#include "project.h"
+
+
+
+void show(DISK *d)
+{
+MBR *m;
+GPT_header *h;
+GPT_entry *e;
+
+uint8_t buf[512];
+
+disk_read(d,buf,0,1);
+m=(MBR *)buf;
+mbr_show(m);
+
+disk_read(d,buf,1,1);
+h=(GPT_header *)buf;
+header_show(d,h);
+
+disk_read(d,buf,disk_lbas(d)-1,1);
+h=(GPT_header *)buf;
+header_show(d,h);
+
+}
+
+
+
+
+
+
diff --git a/src/util.c b/src/util.c
index 32071fd..6fddd57 100644
--- a/src/util.c
+++ b/src/util.c
@@ -52,4 +52,25 @@ hexdump (FILE * f, uint8_t * data, int s, int l)
}
+void utf16_to_ascii(uint16_t *u16,int u16_len,uint8_t *u8, int u8_len)
+{
+u16_len >>=1;
+
+if (u8_len==1) {
+ *u8=0;
+ return;
+}
+while (*u16 && u16_len) {
+*(u8++)=*(u16++);
+u16_len--;
+u8_len--;
+if (u8_len==1) {
+ *u8=0;
+ return;
+}
+}
+
+ *u8=0;
+ return;
+}