[Yellowstone] add ability to read GPT.
This commit is contained in:
parent
090441ad04
commit
b880c11ac7
|
@ -0,0 +1,138 @@
|
|||
use denali::DenaliClient;
|
||||
use mammoth::{cap::Capability, zion::ZError};
|
||||
|
||||
const MBR_SIG: u16 = 0xAA55;
|
||||
|
||||
const GPT_OS_TYPE: u8 = 0xEE;
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct MbrPartition {
|
||||
boot_indicator: u8,
|
||||
starting_chs: [u8; 3],
|
||||
os_type: u8,
|
||||
ending_chs: [u8; 3],
|
||||
starting_lba: u32,
|
||||
ending_lba: u32,
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct PartitionHeader {
|
||||
signature: u64,
|
||||
revision: u32,
|
||||
header_size: u32,
|
||||
crc_32: u32,
|
||||
reserved: u32,
|
||||
lba_self: u64,
|
||||
lba_mirror: u64,
|
||||
lba_min: u64,
|
||||
lba_max: u64,
|
||||
guid_low: u64,
|
||||
guid_high: u64,
|
||||
lba_partition_entries: u64,
|
||||
num_partitions: u32,
|
||||
partition_entry_size: u32,
|
||||
partition_entry_crc32: u32,
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct PartitionEntry {
|
||||
type_guid_low: u64,
|
||||
type_guid_high: u64,
|
||||
part_guid_low: u64,
|
||||
part_guid_high: u64,
|
||||
lba_start: u64,
|
||||
lba_end: u64,
|
||||
attrs: u64,
|
||||
partition_name: [u8; 72],
|
||||
}
|
||||
|
||||
pub fn read_gpt(mut denali: DenaliClient) -> Result<u64, ZError> {
|
||||
let resp = denali.read(&denali::ReadRequest {
|
||||
device_id: 0,
|
||||
block: denali::DiskBlock { lba: 0, size: 2 },
|
||||
})?;
|
||||
|
||||
let first_lbas = mammoth::mem::MemoryRegion::from_cap(Capability::take(resp.memory))?;
|
||||
|
||||
let maybe_mbr_sig = u16::from_le_bytes(first_lbas.slice()[0x1FE..0x200].try_into().unwrap());
|
||||
|
||||
if maybe_mbr_sig != MBR_SIG {
|
||||
mammoth::debug!("MBR Sig {:#x} does not match {:#x}", maybe_mbr_sig, MBR_SIG);
|
||||
return Err(ZError::FAILED_PRECONDITION);
|
||||
}
|
||||
|
||||
let mbr = unsafe {
|
||||
first_lbas.slice::<u8>()[0x1BE..]
|
||||
.as_ptr()
|
||||
.cast::<MbrPartition>()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
if mbr.os_type != GPT_OS_TYPE {
|
||||
let os_type = mbr.os_type;
|
||||
mammoth::debug!(
|
||||
"MBR OS Type: {:#x} does not match GPT ({:#x})",
|
||||
os_type,
|
||||
GPT_OS_TYPE
|
||||
);
|
||||
}
|
||||
|
||||
let gpt_header = unsafe {
|
||||
first_lbas.slice::<u8>()[512..]
|
||||
.as_ptr()
|
||||
.cast::<PartitionHeader>()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let num_partitions = gpt_header.num_partitions;
|
||||
let partition_entry_size = gpt_header.partition_entry_size;
|
||||
let lba_partition_entries = gpt_header.lba_partition_entries;
|
||||
let num_blocks = (num_partitions * partition_entry_size).div_ceil(512) as u64;
|
||||
|
||||
mammoth::debug!(
|
||||
"Reading partition table from LBA {}, {} entries of size {} equals {} blocks.",
|
||||
lba_partition_entries,
|
||||
num_partitions,
|
||||
partition_entry_size,
|
||||
num_blocks
|
||||
);
|
||||
|
||||
let resp = denali.read(&denali::ReadRequest {
|
||||
device_id: 0,
|
||||
block: denali::DiskBlock {
|
||||
lba: lba_partition_entries,
|
||||
size: num_blocks,
|
||||
},
|
||||
})?;
|
||||
|
||||
let partition_table = mammoth::mem::MemoryRegion::from_cap(Capability::take(resp.memory))?;
|
||||
|
||||
for ind in 0..num_partitions {
|
||||
let offset = (ind * partition_entry_size) as usize;
|
||||
let limit = offset + (partition_entry_size as usize);
|
||||
|
||||
let partition_entry = unsafe {
|
||||
partition_table.slice::<u8>()[offset..limit]
|
||||
.as_ptr()
|
||||
.cast::<PartitionEntry>()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
if partition_entry.type_guid_low == 0 && partition_entry.type_guid_high == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
const LFS_DATA_LOW: u64 = 0x477284830fc63daf;
|
||||
const LFS_DATA_HIGH: u64 = 0xe47d47d8693d798e;
|
||||
if partition_entry.type_guid_low == LFS_DATA_LOW
|
||||
&& partition_entry.type_guid_high == LFS_DATA_HIGH
|
||||
{
|
||||
return Ok(partition_entry.lba_start);
|
||||
}
|
||||
}
|
||||
|
||||
Err(ZError::NOT_FOUND)
|
||||
}
|
|
@ -13,6 +13,7 @@ use mammoth::{
|
|||
use yellowstone_yunq::YellowstoneServer;
|
||||
use yunq::server::YunqServer;
|
||||
|
||||
mod gpt;
|
||||
mod pci;
|
||||
mod server;
|
||||
|
||||
|
|
|
@ -88,6 +88,19 @@ impl YellowstoneServerHandler for YellowstoneServerImpl {
|
|||
}
|
||||
|
||||
fn get_denali(&mut self) -> Result<DenaliInfo, ZError> {
|
||||
todo!()
|
||||
match self.service_map.get("denali") {
|
||||
Some(ep_cap) => crate::gpt::read_gpt(denali::DenaliClient::new(
|
||||
ep_cap.duplicate(Capability::PERMS_ALL).unwrap(),
|
||||
))
|
||||
.map(|lba| DenaliInfo {
|
||||
denali_endpoint: ep_cap.duplicate(Capability::PERMS_ALL).unwrap().release(),
|
||||
device_id: 0,
|
||||
lba_offset: lba,
|
||||
}),
|
||||
None => {
|
||||
mammoth::debug!("Denali not yet registered");
|
||||
Err(ZError::FAILED_PRECONDITION)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue