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:
Axel Dörfler
2007-06-30 15:24:03 +00:00
parent 4be1917dda
commit 7ab2a36254
5 changed files with 338 additions and 1 deletions
@@ -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 */