Skip to content
Snippets Groups Projects
Commit ff0f0200 authored by Ann Priestman's avatar Ann Priestman
Browse files

Add support for loading secondary GPT

parent 9f21ddf1
Branches
No related tags found
No related merge requests found
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* It is loaded into the internal sorted list * It is loaded into the internal sorted list
*/ */
static uint8_t static uint8_t
gpt_load_table(TSK_VS_INFO * vs) gpt_load_table(TSK_VS_INFO * vs, GPT_TYPE_ENUM gpt_type)
{ {
gpt_head *head; gpt_head *head;
gpt_entry *ent; gpt_entry *ent;
...@@ -32,68 +32,94 @@ gpt_load_table(TSK_VS_INFO * vs) ...@@ -32,68 +32,94 @@ gpt_load_table(TSK_VS_INFO * vs)
char *safe_str, *head_str, *tab_str, *ent_buf; char *safe_str, *head_str, *tab_str, *ent_buf;
ssize_t cnt; ssize_t cnt;
char *sect_buf; char *sect_buf;
TSK_DADDR_T taddr = vs->offset / vs->block_size + GPT_PART_SOFFSET;
TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size; // max sector TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size; // max sector
TSK_DADDR_T gpt_relative_addr;
TSK_DADDR_T gpt_absolute_addr;
TSK_DADDR_T dos_sect_relative_addr;
TSK_DADDR_T dos_sect_absolute_addr;
if(gpt_type == PRIMARY_TABLE){
dos_sect_relative_addr = GPT_PART_SOFFSET;
dos_sect_absolute_addr = vs->offset / vs->block_size + GPT_PART_SOFFSET;
gpt_relative_addr = GPT_PART_SOFFSET + 1;
gpt_absolute_addr = vs->offset / vs->block_size + GPT_PART_SOFFSET + 1;
} else {
gpt_relative_addr = ((vs->img_info->size - vs->offset) / vs->block_size) - 1;
gpt_absolute_addr = (vs->img_info->size / vs->block_size) - 1;
}
if (tsk_verbose) if (tsk_verbose)
tsk_fprintf(stderr, "gpt_load_table: Sector: %" PRIuDADDR "\n", tsk_fprintf(stderr, "gpt_load_table: Sector: %" PRIuDADDR "\n",
taddr); gpt_absolute_addr);
if ((sect_buf = tsk_malloc(vs->block_size)) == NULL) if ((sect_buf = tsk_malloc(vs->block_size)) == NULL)
return 1; return 1;
dos_part = (dos_sect *) sect_buf;
cnt = tsk_vs_read_block if(gpt_type == PRIMARY_TABLE){
(vs, GPT_PART_SOFFSET, sect_buf, vs->block_size); dos_part = (dos_sect *) sect_buf;
/* if -1, then tsk_errno is already set */
if (cnt != vs->block_size) { cnt = tsk_vs_read_block
if (cnt >= 0) { (vs, dos_sect_relative_addr, sect_buf, vs->block_size);
tsk_error_reset(); /* if -1, then tsk_errno is already set */
tsk_error_set_errno(TSK_ERR_VS_READ); if (cnt != vs->block_size) {
if (cnt >= 0) {
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_VS_READ);
}
tsk_error_set_errstr2
("Error reading DOS safety partition table in Sector: %"
PRIuDADDR, dos_sect_absolute_addr);
free(sect_buf);
return 1;
} }
tsk_error_set_errstr2
("Error reading DOS safety partition table in Sector: %"
PRIuDADDR, taddr);
free(sect_buf);
return 1;
}
/* Sanity Check */ /* Sanity Check */
if (tsk_vs_guessu16(vs, dos_part->magic, DOS_MAGIC)) { if (tsk_vs_guessu16(vs, dos_part->magic, DOS_MAGIC)) {
tsk_error_reset(); tsk_error_reset();
tsk_error_set_errno(TSK_ERR_VS_MAGIC); tsk_error_set_errno(TSK_ERR_VS_MAGIC);
tsk_error_set_errstr tsk_error_set_errstr
("Missing DOS safety partition (invalid magic) (Sector: %" ("Missing DOS safety partition (invalid magic) (Sector: %"
PRIuDADDR ")", taddr); PRIuDADDR ")", dos_sect_absolute_addr);
free(sect_buf); free(sect_buf);
return 1; return 1;
} }
if (dos_part->ptable[0].ptype != GPT_DOS_TYPE) { if (dos_part->ptable[0].ptype != GPT_DOS_TYPE) {
tsk_error_reset(); tsk_error_reset();
tsk_error_set_errno(TSK_ERR_VS_MAGIC); tsk_error_set_errno(TSK_ERR_VS_MAGIC);
tsk_error_set_errstr tsk_error_set_errstr
("Missing DOS safety partition (invalid type in table: %d)", ("Missing DOS safety partition (invalid type in table: %d)",
dos_part->ptable[0].ptype); dos_part->ptable[0].ptype);
free(sect_buf); free(sect_buf);
return 1; return 1;
}
} }
/* Read the GPT header */ /* Read the GPT header */
head = (gpt_head *) sect_buf; head = (gpt_head *) sect_buf;
cnt = tsk_vs_read_block cnt = tsk_vs_read_block
(vs, GPT_PART_SOFFSET + 1, sect_buf, vs->block_size); (vs, gpt_relative_addr, sect_buf, vs->block_size);
if (cnt != vs->block_size) { if (cnt != vs->block_size) {
if (cnt >= 0) { if (cnt >= 0) {
tsk_error_reset(); tsk_error_reset();
tsk_error_set_errno(TSK_ERR_VS_READ); tsk_error_set_errno(TSK_ERR_VS_READ);
} }
tsk_error_set_errstr2("GPT Header structure in Sector: %" tsk_error_set_errstr2("GPT Header structure in Sector: %"
PRIuDADDR, taddr + 1); PRIuDADDR, gpt_absolute_addr);
free(sect_buf); free(sect_buf);
return 1; return 1;
} }
/* Do the endianness test for the secondary table since the test in the dos safety table was skipped */
if(gpt_type == SECONDARY_TABLE){
if(tsk_getu64(TSK_BIG_ENDIAN, head->head_lba) == gpt_relative_addr){
vs->endian = TSK_BIG_ENDIAN;
} else {
vs->endian = TSK_LIT_ENDIAN;
}
}
if (tsk_getu64(vs->endian, &head->signature) != GPT_HEAD_SIG) { if (tsk_getu64(vs->endian, &head->signature) != GPT_HEAD_SIG) {
tsk_error_reset(); tsk_error_reset();
tsk_error_set_errno(TSK_ERR_VS_MAGIC); tsk_error_set_errno(TSK_ERR_VS_MAGIC);
...@@ -109,21 +135,22 @@ gpt_load_table(TSK_VS_INFO * vs) ...@@ -109,21 +135,22 @@ gpt_load_table(TSK_VS_INFO * vs)
return 1; return 1;
} }
snprintf(safe_str, 16, "Safety Table"); if(gpt_type == PRIMARY_TABLE){
if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 0, (TSK_DADDR_T) 1, snprintf(safe_str, 16, "Safety Table");
TSK_VS_PART_FLAG_META, safe_str, -1, -1)) { if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 0, (TSK_DADDR_T) 1,
free(sect_buf); TSK_VS_PART_FLAG_META, safe_str, -1, -1)) {
return 1; free(sect_buf);
return 1;
}
} }
if ((head_str = tsk_malloc(16)) == NULL) { if ((head_str = tsk_malloc(16)) == NULL) {
free(sect_buf); free(sect_buf);
return 1; return 1;
} }
snprintf(head_str, 16, "GPT Header"); snprintf(head_str, 16, "GPT Header");
if (NULL == tsk_vs_part_add(vs, (TSK_DADDR_T) 1, if (NULL == tsk_vs_part_add(vs, gpt_relative_addr,
(TSK_DADDR_T) ((tsk_getu32(vs->endian, (TSK_DADDR_T) ((tsk_getu32(vs->endian,
&head->head_size_b) + (vs->block_size - &head->head_size_b) + (vs->block_size -
1)) / vs->block_size), TSK_VS_PART_FLAG_META, 1)) / vs->block_size), TSK_VS_PART_FLAG_META,
...@@ -303,7 +330,7 @@ tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) ...@@ -303,7 +330,7 @@ tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset)
vs->close = gpt_close; vs->close = gpt_close;
/* Load the partitions into the sorted list */ /* Load the partitions into the sorted list */
if (gpt_load_table(vs)) { if (gpt_load_table(vs, PRIMARY_TABLE)) {
int found = 0; int found = 0;
if (tsk_verbose) if (tsk_verbose)
tsk_fprintf(stderr, "gpt_open: Trying other sector sizes\n"); tsk_fprintf(stderr, "gpt_open: Trying other sector sizes\n");
...@@ -315,7 +342,7 @@ tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) ...@@ -315,7 +342,7 @@ tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset)
tsk_fprintf(stderr, "gpt_open: Trying sector size: %d\n", tsk_fprintf(stderr, "gpt_open: Trying sector size: %d\n",
vs->block_size); vs->block_size);
if (gpt_load_table(vs)) { if (gpt_load_table(vs, PRIMARY_TABLE)) {
vs->block_size *= 2; vs->block_size *= 2;
continue; continue;
} }
...@@ -324,8 +351,33 @@ tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset) ...@@ -324,8 +351,33 @@ tsk_vs_gpt_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset)
} }
if (found == 0) { if (found == 0) {
gpt_close(vs); /* Look for the secondary GPT at the end of the image */
return NULL; if (tsk_verbose)
tsk_fprintf(stderr, "gpt_open: Trying secondary table\n");
vs->block_size = img_info->sector_size;
if(gpt_load_table(vs, SECONDARY_TABLE)){
/* Try other sector sizes again */
vs->block_size = 512;
while (vs->block_size <= 8192) {
if (tsk_verbose)
tsk_fprintf(stderr, "gpt_open: Trying secondary table sector size: %d\n",
vs->block_size);
if (gpt_load_table(vs, SECONDARY_TABLE)) {
vs->block_size *= 2;
continue;
}
found = 1;
break;
}
if(found == 0){
gpt_close(vs);
return NULL;
}
}
} }
} }
......
...@@ -57,6 +57,11 @@ extern "C" { ...@@ -57,6 +57,11 @@ extern "C" {
uint8_t name[72]; /* name in unicode */ uint8_t name[72]; /* name in unicode */
} gpt_entry; } gpt_entry;
typedef enum {
PRIMARY_TABLE,
SECONDARY_TABLE,
} GPT_TYPE_ENUM;
#ifdef __cplusplus #ifdef __cplusplus
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment