mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:27:45 +00:00
Kernel: Allow to boot from a partition with partition UUID
Instead of specifying the boot argument to be root=/dev/hdXY, now one can write root=PARTUUID= with the right UUID, and if the partition is found, the kernel will boot from it. This feature is mainly used with GUID partitions, and is considered to be the most reliable way for the kernel to identify partitions.
This commit is contained in:
parent
d22d29a29a
commit
9dc8bea3e7
9 changed files with 162 additions and 62 deletions
|
@ -47,6 +47,11 @@ DiskPartition::~DiskPartition()
|
|||
{
|
||||
}
|
||||
|
||||
const DiskPartitionMetadata& DiskPartition::metadata() const
|
||||
{
|
||||
return m_metadata;
|
||||
}
|
||||
|
||||
void DiskPartition::start_request(AsyncBlockDeviceRequest& request)
|
||||
{
|
||||
request.add_sub_request(m_device->make_request<AsyncBlockDeviceRequest>(request.request_type(),
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
// ^Device
|
||||
virtual mode_t required_mode() const override { return 0600; }
|
||||
|
||||
const DiskPartitionMetadata& metadata() const;
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override;
|
||||
|
||||
|
|
|
@ -24,31 +24,72 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <AK/AllOf.h>
|
||||
#include <Kernel/Storage/Partition/DiskPartitionMetadata.h>
|
||||
|
||||
namespace Kernel {
|
||||
DiskPartitionMetadata::DiskPartitionMetadata(u64 start_block, u64 end_block, ByteBuffer partition_type)
|
||||
: m_start_block(start_block)
|
||||
, m_end_block(end_block)
|
||||
, m_partition_type(partition_type)
|
||||
|
||||
DiskPartitionMetadata::PartitionType::PartitionType(u8 partition_type)
|
||||
{
|
||||
ASSERT(!m_partition_type.is_empty());
|
||||
m_partition_type[0] = partition_type;
|
||||
}
|
||||
DiskPartitionMetadata::DiskPartitionMetadata(u64 start_block, u64 end_block, ByteBuffer partition_guid, ByteBuffer unique_guid, u64 special_attributes, String name)
|
||||
DiskPartitionMetadata::PartitionType::PartitionType(Array<u8, 16> partition_type)
|
||||
: m_partition_type_is_uuid(true)
|
||||
{
|
||||
m_partition_type.span().overwrite(0, partition_type.data(), partition_type.size());
|
||||
}
|
||||
UUID DiskPartitionMetadata::PartitionType::to_uuid() const
|
||||
{
|
||||
ASSERT(is_uuid());
|
||||
return m_partition_type;
|
||||
}
|
||||
u8 DiskPartitionMetadata::PartitionType::to_byte_indicator() const
|
||||
{
|
||||
ASSERT(!is_uuid());
|
||||
return m_partition_type[0];
|
||||
}
|
||||
bool DiskPartitionMetadata::PartitionType::is_uuid() const
|
||||
{
|
||||
return m_partition_type_is_uuid;
|
||||
}
|
||||
bool DiskPartitionMetadata::PartitionType::is_valid() const
|
||||
{
|
||||
return !all_of(m_partition_type.begin(), m_partition_type.end(), [](const auto octet) { return octet == 0; });
|
||||
}
|
||||
|
||||
DiskPartitionMetadata::DiskPartitionMetadata(u64 start_block, u64 end_block, u8 partition_type)
|
||||
: m_start_block(start_block)
|
||||
, m_end_block(end_block)
|
||||
, m_partition_type(partition_guid)
|
||||
, m_type(partition_type)
|
||||
{
|
||||
|
||||
ASSERT(m_type.is_valid());
|
||||
}
|
||||
|
||||
DiskPartitionMetadata::DiskPartitionMetadata(u64 start_block, u64 end_block, Array<u8, 16> partition_type)
|
||||
: m_start_block(start_block)
|
||||
, m_end_block(end_block)
|
||||
, m_type(partition_type)
|
||||
{
|
||||
|
||||
ASSERT(m_type.is_valid());
|
||||
}
|
||||
|
||||
DiskPartitionMetadata::DiskPartitionMetadata(u64 start_block, u64 end_block, Array<u8, 16> partition_type, UUID unique_guid, u64 special_attributes, String name)
|
||||
: m_start_block(start_block)
|
||||
, m_end_block(end_block)
|
||||
, m_type(partition_type)
|
||||
, m_unique_guid(unique_guid)
|
||||
, m_attributes(special_attributes)
|
||||
, m_name(name)
|
||||
{
|
||||
ASSERT(!m_partition_type.is_empty());
|
||||
ASSERT(!m_unique_guid.is_empty());
|
||||
ASSERT(m_type.is_valid());
|
||||
ASSERT(!m_unique_guid.is_zero());
|
||||
}
|
||||
|
||||
DiskPartitionMetadata DiskPartitionMetadata::offset(u64 blocks_count) const
|
||||
{
|
||||
return DiskPartitionMetadata({ blocks_count + m_start_block, blocks_count + m_end_block, m_partition_type });
|
||||
return { blocks_count + m_start_block, blocks_count + m_end_block, m_type.m_partition_type };
|
||||
}
|
||||
|
||||
u64 DiskPartitionMetadata::start_block() const
|
||||
|
@ -71,16 +112,12 @@ Optional<String> DiskPartitionMetadata::name() const
|
|||
return {};
|
||||
return m_name;
|
||||
}
|
||||
Optional<ByteBuffer> DiskPartitionMetadata::partition_type() const
|
||||
const DiskPartitionMetadata::PartitionType& DiskPartitionMetadata::type() const
|
||||
{
|
||||
if (m_partition_type.is_null() || m_partition_type.is_empty())
|
||||
return {};
|
||||
return m_partition_type;
|
||||
return m_type;
|
||||
}
|
||||
Optional<ByteBuffer> DiskPartitionMetadata::unique_guid() const
|
||||
const UUID& DiskPartitionMetadata::unique_guid() const
|
||||
{
|
||||
if (m_unique_guid.is_null() || m_unique_guid.is_empty())
|
||||
return {};
|
||||
return m_unique_guid;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,14 +27,33 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/UUID.h>
|
||||
#include <Kernel/Devices/BlockDevice.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class DiskPartitionMetadata {
|
||||
private:
|
||||
class PartitionType {
|
||||
friend class DiskPartitionMetadata;
|
||||
|
||||
public:
|
||||
explicit PartitionType(u8 partition_type);
|
||||
explicit PartitionType(Array<u8, 16> partition_type);
|
||||
UUID to_uuid() const;
|
||||
u8 to_byte_indicator() const;
|
||||
bool is_uuid() const;
|
||||
bool is_valid() const;
|
||||
|
||||
private:
|
||||
Array<u8, 16> m_partition_type {};
|
||||
bool m_partition_type_is_uuid { false };
|
||||
};
|
||||
|
||||
public:
|
||||
DiskPartitionMetadata(u64 block_offset, u64 block_limit, ByteBuffer partition_type);
|
||||
DiskPartitionMetadata(u64 block_offset, u64 block_limit, ByteBuffer partition_type, ByteBuffer unique_guid, u64 special_attributes, String name);
|
||||
DiskPartitionMetadata(u64 block_offset, u64 block_limit, u8 partition_type);
|
||||
DiskPartitionMetadata(u64 start_block, u64 end_block, Array<u8, 16> partition_type);
|
||||
DiskPartitionMetadata(u64 block_offset, u64 block_limit, Array<u8, 16> partition_type, UUID unique_guid, u64 special_attributes, String name);
|
||||
u64 start_block() const;
|
||||
u64 end_block() const;
|
||||
|
||||
|
@ -42,14 +61,14 @@ public:
|
|||
|
||||
Optional<u64> special_attributes() const;
|
||||
Optional<String> name() const;
|
||||
Optional<ByteBuffer> partition_type() const;
|
||||
Optional<ByteBuffer> unique_guid() const;
|
||||
const PartitionType& type() const;
|
||||
const UUID& unique_guid() const;
|
||||
|
||||
private:
|
||||
u64 m_start_block;
|
||||
u64 m_end_block;
|
||||
ByteBuffer m_partition_type;
|
||||
ByteBuffer m_unique_guid;
|
||||
PartitionType m_type;
|
||||
UUID m_unique_guid {};
|
||||
u64 m_attributes { 0 };
|
||||
String m_name;
|
||||
};
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/AllOf.h>
|
||||
#include <AK/Array.h>
|
||||
#include <Kernel/Storage/Partition/GUIDPartitionTable.h>
|
||||
|
||||
#ifndef GPT_DEBUG
|
||||
|
@ -121,31 +122,28 @@ bool GUIDPartitionTable::initialize()
|
|||
}
|
||||
auto* entries = (const GPTPartitionEntry*)entries_buffer.data();
|
||||
auto& entry = entries[entry_index % (m_device->block_size() / (size_t)header().partition_entry_size)];
|
||||
ByteBuffer partition_type = ByteBuffer::copy(entry.partition_guid, 16);
|
||||
Array<u8, 16> partition_type {};
|
||||
partition_type.span().overwrite(0, entry.partition_guid, partition_type.size());
|
||||
|
||||
if (is_unused_entry(partition_type)) {
|
||||
raw_byte_index += header().partition_entry_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
ByteBuffer unique_guid = ByteBuffer::copy(entry.unique_guid, 16);
|
||||
Array<u8, 16> unique_guid {};
|
||||
unique_guid.span().overwrite(0, entry.unique_guid, unique_guid.size());
|
||||
String name = entry.partition_name;
|
||||
dbg() << "Detected GPT partition (entry " << entry_index << ") , offset " << entry.first_lba << " , limit " << entry.last_lba;
|
||||
m_partitions.append(DiskPartitionMetadata({ entry.first_lba, entry.last_lba, partition_type }));
|
||||
m_partitions.append({ entry.first_lba, entry.last_lba, partition_type, unique_guid, entry.attributes, "" });
|
||||
raw_byte_index += header().partition_entry_size;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUIDPartitionTable::is_unused_entry(ByteBuffer partition_type) const
|
||||
bool GUIDPartitionTable::is_unused_entry(Array<u8, 16> partition_type) const
|
||||
{
|
||||
ASSERT(partition_type.size() == 16);
|
||||
for (size_t byte_index = 0; byte_index < 16; byte_index++) {
|
||||
if (partition_type[byte_index] != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return all_of(partition_type.begin(), partition_type.end(), [](const auto octet) { return octet == 0; });
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
virtual bool is_valid() const override { return m_valid; };
|
||||
|
||||
private:
|
||||
bool is_unused_entry(ByteBuffer) const;
|
||||
bool is_unused_entry(Array<u8, 16>) const;
|
||||
const GUIDPartitionHeader& header() const;
|
||||
bool initialize();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue