Skip to content

Commit

Permalink
add support for disks using a GUID Partition Table
Browse files Browse the repository at this point in the history
  • Loading branch information
hackedd committed Oct 2, 2013
1 parent 2269e50 commit e4bd4ba
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 2 deletions.
3 changes: 2 additions & 1 deletion ext2explore.pro
Expand Up @@ -25,7 +25,8 @@ HEADERS += platform.h \
partition.h \
ext2properties.h \
ext2about.h \
ext2copyfile.h
ext2copyfile.h \
gpt.h
FORMS += ext2explore.ui \
properties.ui \
about.ui \
Expand Down
79 changes: 78 additions & 1 deletion ext2read.cpp
Expand Up @@ -32,7 +32,7 @@
#include "partition.h"
#include "parttypes.h"
#include "lvm.h"

#include "gpt.h"


Ext2Read::Ext2Read()
Expand Down Expand Up @@ -160,6 +160,77 @@ int Ext2Read::scan_ebr(FileHandle handle, lloff_t base, int sectsize, int disk)
return logical;
}

/* Reads a GUID Partion Table */
int Ext2Read::scan_gpt(FileHandle handle, lloff_t base, int sectsize, int disk)
{
unsigned char sector[SECTOR_SIZE];
struct GPTHeader header;
struct GPTPartition entry;
Ext2Partition *partition;
char guid_buf[40];
uint32_t i;
int ret, j, entries_per_sector;
lloff_t offset;

ret = read_disk(handle, sector, base, 1, sectsize);
if(ret < 0)
return ret;

/* Fill the header structure with data from the sector. */
memcpy(&header, sector, sizeof(struct GPTHeader));
if (!valid_gpt_header(&header))
{
LOG("Not a valid GPT Header\n");
return 0;
}

if ((sectsize % header.entry_size) != 0)
{
LOG_ERROR("Sector size (%d bytes) is not a multiple of GPT Entry size "
"(%d bytes)\n", sectsize, header.entry_size);
return 0;
}

entries_per_sector = sectsize / header.entry_size;
offset = header.partition_lba;
for (i = 0; i < header.num_partitions; i += entries_per_sector)
{
ret = read_disk(handle, sector, offset, 1, sectsize);
if (ret < 0)
return ret;
offset += 1;

for (j = 0; j < entries_per_sector; j += 1)
{
memcpy(&entry, sector + j * sizeof(struct GPTPartition), sizeof(struct GPTPartition));
if (gpt_guid_equal(&entry.type_guid, &gpt_guid_none))
continue;

gpt_guid_to_string(guid_buf, &entry.type_guid);
LOG("Found GPT Partition '%ls' - %s\n", entry.name, guid_buf);

if (gpt_guid_equal(&entry.type_guid, &gpt_guid_ms_basic_data) ||
gpt_guid_equal(&entry.type_guid, &gpt_guid_linux_fs_data) ||
gpt_guid_equal(&entry.type_guid, &gpt_guid_linux_home))
{
partition = new Ext2Partition(entry.last_lba - entry.first_lba,
entry.first_lba, sectsize, handle, NULL);
if (partition->is_valid)
{
partition->set_linux_name("/dev/sd", disk, i + j);
nparts.push_back(partition);
LOG("Linux Partition found on disk %d GPT partition %d\n", disk, i + j);
}
else
{
delete partition;
}
}
}
}

return 0;
}

/* Scans The partitions */
int Ext2Read::scan_partitions(char *path, int diskno)
Expand Down Expand Up @@ -225,6 +296,12 @@ int Ext2Read::scan_partitions(char *path, int diskno)
{
scan_ebr(handle, get_start_sect(part), sector_size, diskno);
}
else if (part->sys_ind == 0xEE)
{
/* If the disk contains a GPT, the so-called Protective MBR
* contains one partition of type EE spanning the entire disk. */
scan_gpt(handle, get_start_sect(part), sector_size, diskno);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions ext2read.h
Expand Up @@ -193,6 +193,7 @@ class Ext2Read {
list <Ext2Partition *> nparts;

int scan_ebr(FileHandle , lloff_t , int , int);
int scan_gpt(FileHandle , lloff_t , int , int);
int scan_partitions(char *path, int);
void clear_partitions();

Expand Down
89 changes: 89 additions & 0 deletions gpt.h
@@ -0,0 +1,89 @@
/**
* Copyright (C) 2013 by Paul Hooijenga (paulhooijenga at gmail.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**/
#ifndef __GPT_H
#define __GPT_H

#include <stdint.h>
#include <stdio.h>

#include "platform.h"

struct GPTGuid {
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint64_t Data4;
};

struct GPTHeader {
char signature[8];
uint32_t revision;
uint32_t size;
uint32_t crc32;
uint32_t reserved;
uint64_t current_lba;
uint64_t backup_lba;
uint64_t first_lba;
uint64_t last_lba;
struct GPTGuid disk_guid;
uint64_t partition_lba;
uint32_t num_partitions;
uint32_t entry_size;
uint32_t array_crc32;
};

struct GPTPartition {
struct GPTGuid type_guid;
struct GPTGuid guid;
uint64_t first_lba;
uint64_t last_lba;
uint64_t flags;
uint16_t name[36]; /* UTF-16 LE */
};

#define GPT_HEADER_SIGNATURE "EFI PART"

static INLINE int valid_gpt_header(const struct GPTHeader* header) {
return memcmp(header->signature, GPT_HEADER_SIGNATURE, sizeof(header->signature)) == 0;
}

static INLINE int gpt_guid_equal(const struct GPTGuid* a, const struct GPTGuid* b) {
return memcmp(a, b, sizeof(struct GPTGuid)) == 0;
}

static INLINE int gpt_guid_to_string(char* buf, const struct GPTGuid* guid) {
unsigned char data4[8];
memcpy(data4, &guid->Data4, sizeof(uint64_t));

return sprintf(buf, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
guid->Data1, guid->Data2, guid->Data3,
data4[0], data4[1], data4[2], data4[3],
data4[4], data4[5], data4[6], data4[7]);
}

#define GPT_GUID(name, data1, data2, data3, data4a, data4b) \
const struct GPTGuid gpt_guid_##name = { data1, data2, data3, __builtin_bswap64((uint64_t)data4a << 48 | data4b) }

GPT_GUID(none, 0x00000000, 0x0000, 0x0000, 0x0000, 0x000000000000LL);
GPT_GUID(ms_reserved, 0xE3C9E316, 0x0B5C, 0x4DB8, 0x817D, 0xF92DF00215AELL);
GPT_GUID(ms_basic_data, 0xEBD0A0A2, 0xB9E5, 0x4433, 0x87C0, 0x68B6B72699C7LL);
GPT_GUID(linux_fs_data, 0x0FC63DAF, 0x8483, 0x4772, 0x8E79, 0x3D69D8477DE4LL);
GPT_GUID(linux_home, 0x933AC7E1, 0x2EB4, 0x4F13, 0xB844, 0x0E14E2AEF915LL);

#endif // __GPT_H

0 comments on commit e4bd4ba

Please sign in to comment.