コード例 #1
0
status_t
Header::Write(int fd)
{
	// Try to write the protective MBR
	PartitionMap partitionMap;
	PrimaryPartition *partition = NULL;
	uint32 index = 0;
	while ((partition = partitionMap.PrimaryPartitionAt(index)) != NULL) {
		if (index == 0) {
			uint64 deviceSize = fHeader.AlternateBlock() * fBlockSize;
			partition->SetTo(fBlockSize, deviceSize, 0xEE, false, fBlockSize);
		} else
			partition->Unset();
		++index;
	}
	PartitionMapWriter writer(fd, fBlockSize);
	writer.WriteMBR(&partitionMap, true);
		// We also write the bootcode, so we can boot GPT disks from BIOS

	status_t status = _Write(fd, fHeader.EntriesBlock() * fBlockSize, fEntries,
		_EntryArraySize());
	if (status != B_OK)
		return status;

	// First write the header, so that we have at least one completely correct
	// data set
	status = _WriteHeader(fd);


	// Write backup entries
	status_t backupStatus = _Write(fd,
		fBackupHeader.EntriesBlock() * fBlockSize, fEntries, _EntryArraySize());

	return status == B_OK ? backupStatus : status;
}
コード例 #2
0
ファイル: Header.cpp プロジェクト: kodybrown/haiku
void
Header::_UpdateCRC(efi_table_header& header)
{
	header.SetEntriesCRC(crc32(fEntries, _EntryArraySize()));
	header.SetHeaderCRC(0);
	header.SetHeaderCRC(crc32((uint8*)&header, sizeof(efi_table_header)));
}
コード例 #3
0
ファイル: Header.cpp プロジェクト: kodybrown/haiku
void
Header::_SetBackupHeaderFromPrimary(uint64 lastBlock)
{
	fBackupHeader = fHeader;
	fBackupHeader.SetAbsoluteBlock(lastBlock);
	fBackupHeader.SetEntriesBlock(
		lastBlock - _EntryArraySize() / fBlockSize);
	fBackupHeader.SetAlternateBlock(1);
}
コード例 #4
0
ファイル: Header.cpp プロジェクト: kodybrown/haiku
status_t
Header::Write(int fd)
{
	status_t status = _Write(fd, fHeader.EntriesBlock() * fBlockSize, fEntries,
		_EntryArraySize());
	if (status != B_OK)
		return status;

	// First write the header, so that we have at least one completely correct
	// data set
	status = _WriteHeader(fd);

	// Write backup entries
	status_t backupStatus = _Write(fd,
		fBackupHeader.EntriesBlock() * fBlockSize, fEntries, _EntryArraySize());

	return status == B_OK ? backupStatus : status;
}
コード例 #5
0
Header::Header(uint64 lastBlock, uint32 blockSize)
	:
	fBlockSize(blockSize),
	fStatus(B_NO_INIT),
	fEntries(NULL)
{
	TRACE(("EFI::Header: Initialize GPT, block size %" B_PRIu32 "\n",
		blockSize));

	// Initialize to an empty header
	memcpy(fHeader.header, EFI_PARTITION_HEADER, sizeof(fHeader.header));
	fHeader.SetRevision(EFI_TABLE_REVISION);
	fHeader.SetHeaderSize(sizeof(fHeader));
	fHeader.SetHeaderCRC(0);
	fHeader.SetAbsoluteBlock(EFI_HEADER_LOCATION);
	fHeader.SetAlternateBlock(lastBlock);
	uuid_t uuid;
	uuid_generate_random(uuid);
	memcpy((uint8*)&fHeader.disk_guid, uuid, sizeof(guid_t));
	fHeader.SetEntriesBlock(EFI_PARTITION_ENTRIES_BLOCK);
	fHeader.SetEntryCount(EFI_PARTITION_ENTRY_COUNT);
	fHeader.SetEntrySize(EFI_PARTITION_ENTRY_SIZE);
	fHeader.SetEntriesCRC(0);

	size_t arraySize = _EntryArraySize();
	fEntries = new (std::nothrow) uint8[arraySize];
	if (fEntries == NULL) {
		fStatus = B_NO_MEMORY;
		return;
	}

	memset(fEntries, 0, arraySize);
		// TODO: initialize the entry guids

	uint32 entryBlocks = (arraySize + fBlockSize - 1) / fBlockSize;
	fHeader.SetFirstUsableBlock(EFI_PARTITION_ENTRIES_BLOCK + entryBlocks);
	fHeader.SetLastUsableBlock(lastBlock - 1 - entryBlocks);

	_SetBackupHeaderFromPrimary(lastBlock);

#ifdef TRACE_EFI_GPT
	_Dump(fHeader);
	_DumpPartitions();
#endif

	fStatus = B_OK;
}
コード例 #6
0
ファイル: Header.cpp プロジェクト: kodybrown/haiku
Header::Header(int fd, uint64 lastBlock, uint32 blockSize)
	:
	fBlockSize(blockSize),
	fStatus(B_NO_INIT),
	fEntries(NULL)
{
	// TODO: check the correctness of the protective MBR and warn if invalid

	// Read and check the partition table header

	fStatus = _Read(fd, (uint64)EFI_HEADER_LOCATION * blockSize,
		&fHeader, sizeof(efi_table_header));
	if (fStatus == B_OK) {
		if (!_IsHeaderValid(fHeader, EFI_HEADER_LOCATION))
			fStatus = B_BAD_DATA;
	}

	if (fStatus == B_OK && lastBlock != fHeader.AlternateBlock()) {
		dprintf("gpt: alternate header not in last block (%" B_PRIu64 " vs. %"
			B_PRIu64 ")\n", fHeader.AlternateBlock(), lastBlock);
		lastBlock = fHeader.AlternateBlock();
	}

	// Read backup header, too
	status_t status = _Read(fd, lastBlock * blockSize, &fBackupHeader,
		sizeof(efi_table_header));
	if (status == B_OK) {
		if (!_IsHeaderValid(fBackupHeader, lastBlock))
			status = B_BAD_DATA;
	}

	// If both headers are invalid, bail out -- this is probably not a GPT disk
	if (status != B_OK && fStatus != B_OK)
		return;

	if (fStatus != B_OK) {
		// Recreate primary header from the backup
		fHeader = fBackupHeader;
		fHeader.SetAbsoluteBlock(EFI_HEADER_LOCATION);
		fHeader.SetEntriesBlock(EFI_PARTITION_ENTRIES_BLOCK);
		fHeader.SetAlternateBlock(lastBlock);
	} else if (status != B_OK) {
		// Recreate backup header from primary
		_SetBackupHeaderFromPrimary(lastBlock);
	}

	// 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;
	}

	fStatus = _Read(fd, fHeader.EntriesBlock() * blockSize,
		fEntries, _EntryArraySize());
	if (fStatus != B_OK || !_ValidateEntriesCRC()) {
		// Read backup entries instead
		fStatus = _Read(fd, fBackupHeader.EntriesBlock() * blockSize,
			fEntries, _EntryArraySize());
		if (fStatus != B_OK)
			return;

		if (!_ValidateEntriesCRC()) {
			fStatus = B_BAD_DATA;
			return;
		}
	}

	// TODO: check overlapping or out of range partitions

#ifdef TRACE_EFI_GPT
	_Dump(fHeader);
	_Dump(fBackupHeader);
	_DumpPartitions();
#endif

	fStatus = B_OK;
}
コード例 #7
0
ファイル: Header.cpp プロジェクト: kodybrown/haiku
bool
Header::_ValidateEntriesCRC() const
{
	return fHeader.EntriesCRC() == crc32(fEntries, _EntryArraySize());
}