Beginnings of an EFI partitioning module.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21531 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel partitioning_systems ;
|
SubDir HAIKU_TOP src add-ons kernel partitioning_systems ;
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems intel ;
|
|
||||||
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems amiga ;
|
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems amiga ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems apple ;
|
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems apple ;
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems efi ;
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems intel ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems session ;
|
SubInclude HAIKU_TOP src add-ons kernel partitioning_systems session ;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel partitioning_systems efi ;
|
||||||
|
|
||||||
|
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||||
|
UsePrivateHeaders [ FDirName kernel ] ;
|
||||||
|
UsePrivateHeaders [ FDirName storage ] ;
|
||||||
|
|
||||||
|
KernelAddon efi_gpt :
|
||||||
|
efi_gpt.cpp
|
||||||
|
;
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "efi_gpt.h"
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <ddm_modules.h>
|
||||||
|
#ifdef _BOOT_MODE
|
||||||
|
# include <boot/partitions.h>
|
||||||
|
#else
|
||||||
|
# include <DiskDeviceTypes.h>
|
||||||
|
#endif
|
||||||
|
#include <util/kernel_cpp.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define TRACE_EFI_GPT
|
||||||
|
#ifdef TRACE_EFI_GPT
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define EFI_PARTITION_MODULE_NAME "partitioning_systems/efi_gpt/v1"
|
||||||
|
#define EFI_PARTITION_NAME "EFI GUID Partition Table"
|
||||||
|
|
||||||
|
|
||||||
|
class Header {
|
||||||
|
public:
|
||||||
|
Header(int fd, off_t block, uint32 blockSize);
|
||||||
|
~Header();
|
||||||
|
|
||||||
|
status_t InitCheck();
|
||||||
|
bool IsPrimary() const
|
||||||
|
{ return fBlock == EFI_HEADER_LOCATION; }
|
||||||
|
|
||||||
|
uint32 EntryCount() const
|
||||||
|
{ return fHeader.EntryCount(); }
|
||||||
|
const efi_partition_entry &EntryAt(int32 index) const
|
||||||
|
{ return *(const efi_partition_entry*)
|
||||||
|
(fEntries + fHeader.EntrySize() * index); }
|
||||||
|
|
||||||
|
void Dump();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool _ValidateCRC(uint8 *data, size_t size);
|
||||||
|
size_t _EntryArraySize() const
|
||||||
|
{ return fHeader.EntrySize() * fHeader.EntryCount(); }
|
||||||
|
|
||||||
|
uint64 fBlock;
|
||||||
|
uint32 fBlockSize;
|
||||||
|
status_t fStatus;
|
||||||
|
efi_table_header fHeader;
|
||||||
|
uint8 *fEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Header::Header(int fd, off_t block, uint32 blockSize)
|
||||||
|
:
|
||||||
|
fBlock(block),
|
||||||
|
fBlockSize(blockSize),
|
||||||
|
fStatus(B_NO_INIT),
|
||||||
|
fEntries(NULL)
|
||||||
|
{
|
||||||
|
// TODO: check the correctness of the protective MBR
|
||||||
|
|
||||||
|
// read and check the partition table header
|
||||||
|
|
||||||
|
ssize_t bytesRead = read_pos(fd, block * blockSize, &fHeader, sizeof(fHeader));
|
||||||
|
if (bytesRead != (ssize_t)sizeof(fHeader)) {
|
||||||
|
if (bytesRead < B_OK)
|
||||||
|
fStatus = bytesRead;
|
||||||
|
else
|
||||||
|
fStatus = B_IO_ERROR;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(fHeader.header, EFI_PARTITION_HEADER, sizeof(fHeader.header))
|
||||||
|
|| !_ValidateCRC((uint8 *)&fHeader, sizeof(fHeader))
|
||||||
|
|| fHeader.AbsoluteBlock() != fBlock) {
|
||||||
|
// TODO: check that partition counts are in valid bounds
|
||||||
|
fStatus = B_BAD_DATA;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate, read, and check partition entry array
|
||||||
|
|
||||||
|
fEntries = new (std::nothrow) uint8[_EntryArraySize()];
|
||||||
|
if (fEntries == NULL) {
|
||||||
|
// TODO: if there cannot be allocated enough (ie. the boot loader's
|
||||||
|
// heap is limited), try a smaller size before failing
|
||||||
|
fStatus = B_NO_MEMORY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesRead = read_pos(fd, fHeader.EntriesBlock() * blockSize,
|
||||||
|
fEntries, _EntryArraySize());
|
||||||
|
if (bytesRead != (ssize_t)_EntryArraySize()) {
|
||||||
|
if (bytesRead < B_OK)
|
||||||
|
fStatus = bytesRead;
|
||||||
|
else
|
||||||
|
fStatus = B_IO_ERROR;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_ValidateCRC(fEntries, _EntryArraySize())) {
|
||||||
|
// TODO: check overlapping or out of range partitions
|
||||||
|
fStatus = B_BAD_DATA;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fStatus = B_OK;
|
||||||
|
Dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Header::~Header()
|
||||||
|
{
|
||||||
|
delete[] fEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Header::InitCheck()
|
||||||
|
{
|
||||||
|
return fStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Header::_ValidateCRC(uint8 *data, size_t size)
|
||||||
|
{
|
||||||
|
// TODO: implement!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Header::Dump()
|
||||||
|
{
|
||||||
|
dprintf("entry size: %ld\n", fHeader.EntrySize());
|
||||||
|
dprintf("entry count: %ld\n", fHeader.EntryCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - public module interface
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
efi_gpt_std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static float
|
||||||
|
efi_gpt_identify_partition(int fd, partition_data *partition, void **_cookie)
|
||||||
|
{
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
efi_gpt_scan_partition(int fd, partition_data *partition, void *_cookie)
|
||||||
|
{
|
||||||
|
TRACE(("efi_gpt_scan_partition(cookie = %p)\n", _cookie));
|
||||||
|
|
||||||
|
partition->status = B_PARTITION_VALID;
|
||||||
|
partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
|
||||||
|
| B_PARTITION_READ_ONLY;
|
||||||
|
partition->content_size = partition->size;
|
||||||
|
|
||||||
|
// scan all children
|
||||||
|
|
||||||
|
status_t status;
|
||||||
|
if (status == B_ENTRY_NOT_FOUND)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
efi_gpt_free_identify_partition_cookie(partition_data *partition, void *_cookie)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _BOOT_MODE
|
||||||
|
static partition_module_info sEFIPartitionModule = {
|
||||||
|
#else
|
||||||
|
partition_module_info gEFIPartitionModule = {
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
EFI_PARTITION_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
efi_gpt_std_ops
|
||||||
|
},
|
||||||
|
EFI_PARTITION_NAME, // pretty_name
|
||||||
|
0, // flags
|
||||||
|
|
||||||
|
// scanning
|
||||||
|
efi_gpt_identify_partition,
|
||||||
|
efi_gpt_scan_partition,
|
||||||
|
efi_gpt_free_identify_partition_cookie,
|
||||||
|
NULL,
|
||||||
|
// efi_gpt_free_partition_cookie,
|
||||||
|
// efi_gpt_free_partition_content_cookie,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef _BOOT_MODE
|
||||||
|
partition_module_info *modules[] = {
|
||||||
|
&sEFIPartitionModule,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef EFI_GPT_H
|
||||||
|
#define EFI_GPT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "guid.h"
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct efi_table_header {
|
||||||
|
char header[8];
|
||||||
|
uint32 revision;
|
||||||
|
uint32 header_size;
|
||||||
|
uint32 header_crc;
|
||||||
|
uint32 _reserved1;
|
||||||
|
|
||||||
|
uint64 absolute_block;
|
||||||
|
uint64 alternate_block;
|
||||||
|
uint64 first_usable_block;
|
||||||
|
uint64 last_usable_block;
|
||||||
|
guid_t disk_guid;
|
||||||
|
uint64 entries_block;
|
||||||
|
uint32 entry_count;
|
||||||
|
uint32 entry_size;
|
||||||
|
uint32 entries_crc;
|
||||||
|
|
||||||
|
// the rest of the block is reserved
|
||||||
|
|
||||||
|
uint32 Revision() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT32(revision); }
|
||||||
|
uint32 HeaderSize() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT32(header_size); }
|
||||||
|
uint32 HeaderCRC() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT32(header_crc); }
|
||||||
|
|
||||||
|
uint64 AbsoluteBlock() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT64(absolute_block); }
|
||||||
|
uint64 AlternateBlock() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT64(alternate_block); }
|
||||||
|
uint64 FirstUsableBlock() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT64(first_usable_block); }
|
||||||
|
uint64 LastUsableBlock() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT64(last_usable_block); }
|
||||||
|
|
||||||
|
uint64 EntriesBlock() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT64(entries_block); }
|
||||||
|
uint32 EntryCount() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT32(entry_count); }
|
||||||
|
uint32 EntrySize() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT32(entry_size); }
|
||||||
|
uint32 EntriesCRC() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT32(entries_crc); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EFI_PARTITION_HEADER "EFI PART"
|
||||||
|
#define EFI_HEADER_LOCATION 1
|
||||||
|
|
||||||
|
#define EFI_PARTITION_NAME_LENGTH 36
|
||||||
|
|
||||||
|
struct efi_partition_entry {
|
||||||
|
guid_t partition_type;
|
||||||
|
guid_t unique_guid;
|
||||||
|
uint64 start_lba;
|
||||||
|
uint64 end_lba;
|
||||||
|
uint64 attributes;
|
||||||
|
uint16 name[EFI_PARTITION_NAME_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* EFI_GPT_H */
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2007, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef GUID_H
|
||||||
|
#define GUID_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct guid {
|
||||||
|
uint32 a;
|
||||||
|
uint16 b;
|
||||||
|
uint16 c;
|
||||||
|
uint8 d[8];
|
||||||
|
} _PACKED guid_t;
|
||||||
|
|
||||||
|
#endif /* GUID_H */
|
||||||
|
|
||||||
Reference in New Issue
Block a user