1use crate::sdmmc::{Block, BlockCount, BlockDevice, BlockIdx};
2
3pub fn find_copper_partition<D: BlockDevice>(
5 sd: &D,
6) -> Result<Option<(BlockIdx, BlockCount)>, D::Error> {
7 fn le32(x: &[u8]) -> u32 {
8 u32::from_le_bytes([x[0], x[1], x[2], x[3]])
9 }
10 fn le64(x: &[u8]) -> u64 {
11 u64::from_le_bytes([x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]])
12 }
13
14 const CU29_TYPE_GUID_ONDISK: [u8; 16] = [
16 0xC9, 0xE0, 0xA2, 0x29, 0x00, 0x00, 0x75, 0x4C, 0x92, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00,
17 0x29,
18 ];
19
20 let mut hdr = [Block::new(); 1];
21 read_blocks(sd, &mut hdr, BlockIdx(1), "gpt-lba1")?;
22 let h: &[u8] = &hdr[0].contents;
23 if &h[0..8] != b"EFI PART" {
24 return Ok(None);
25 }
26
27 let ent_lba = le64(&h[72..80]);
28 let num_ents = le32(&h[80..84]) as usize;
29 let ent_sz = le32(&h[84..88]) as usize;
30 if ent_sz == 0 {
31 return Ok(None);
32 }
33
34 let mut remain = num_ents.checked_mul(ent_sz).unwrap_or(0);
35 let mut lba = ent_lba as u32;
36 let mut buf = [Block::new(); 1];
37
38 while remain > 0 {
39 read_blocks(sd, &mut buf, BlockIdx(lba), "gpt-entry")?;
40 let b = &buf[0].contents;
41 let usable = core::cmp::min(remain, Block::LEN);
42
43 let mut off = 0usize;
44 while off + ent_sz <= usable {
45 let e = &b[off..off + ent_sz];
46 if e[0..16] == CU29_TYPE_GUID_ONDISK {
47 let first = le64(&e[32..40]) as u32;
48 let last = le64(&e[40..48]) as u32;
49 if last >= first {
50 return Ok(Some((BlockIdx(first), BlockCount(last - first + 1))));
51 }
52 }
53 off += ent_sz;
54 }
55
56 remain -= usable;
57 lba = lba.saturating_add(1);
58 }
59
60 Ok(None)
61}
62
63#[cfg(all(feature = "eh02", not(feature = "eh1")))]
64fn read_blocks<D: BlockDevice>(
65 dev: &D,
66 blocks: &mut [Block],
67 start_block_idx: BlockIdx,
68 reason: &str,
69) -> Result<(), D::Error> {
70 dev.read(blocks, start_block_idx, reason)
71}
72
73#[cfg(feature = "eh1")]
74fn read_blocks<D: BlockDevice>(
75 dev: &D,
76 blocks: &mut [Block],
77 start_block_idx: BlockIdx,
78 _reason: &str,
79) -> Result<(), D::Error> {
80 dev.read(blocks, start_block_idx)
81}