xref: /DragonOS/kernel/src/driver/open_firmware/fdt.rs (revision 453452cc02e2766a28d87dd47bdee37caddc4c44)
1*453452ccSLoGin use core::mem::size_of;
2*453452ccSLoGin 
345626c85SLoGin use fdt::{
445626c85SLoGin     node::{FdtNode, NodeProperty},
545626c85SLoGin     Fdt,
645626c85SLoGin };
745626c85SLoGin use system_error::SystemError;
845626c85SLoGin 
9*453452ccSLoGin use crate::{
10*453452ccSLoGin     init::boot_params,
11*453452ccSLoGin     libs::rwlock::RwLock,
12*453452ccSLoGin     mm::{memblock::mem_block_manager, PhysAddr},
13*453452ccSLoGin };
1445626c85SLoGin 
1545626c85SLoGin #[inline(always)]
1645626c85SLoGin pub fn open_firmware_fdt_driver() -> &'static OpenFirmwareFdtDriver {
1745626c85SLoGin     &OpenFirmwareFdtDriver
1845626c85SLoGin }
1945626c85SLoGin 
2045626c85SLoGin static FDT_GLOBAL_DATA: RwLock<FdtGlobalData> = RwLock::new(FdtGlobalData::new());
2145626c85SLoGin 
2245626c85SLoGin #[derive(Debug)]
2345626c85SLoGin struct FdtGlobalData {
2445626c85SLoGin     /// FDT根节点下的`size-cells`属性值
2545626c85SLoGin     root_size_cells: u32,
2645626c85SLoGin 
2745626c85SLoGin     /// FDT根节点下的`address-cells`属性值
2845626c85SLoGin     root_addr_cells: u32,
2945626c85SLoGin 
3045626c85SLoGin     chosen_node_name: Option<&'static str>,
3145626c85SLoGin }
3245626c85SLoGin 
3345626c85SLoGin impl FdtGlobalData {
3445626c85SLoGin     pub const fn new() -> Self {
3545626c85SLoGin         Self {
3645626c85SLoGin             root_size_cells: 1,
3745626c85SLoGin             root_addr_cells: 1,
3845626c85SLoGin             chosen_node_name: None,
3945626c85SLoGin         }
4045626c85SLoGin     }
4145626c85SLoGin }
4245626c85SLoGin 
4345626c85SLoGin pub struct OpenFirmwareFdtDriver;
4445626c85SLoGin 
4545626c85SLoGin impl OpenFirmwareFdtDriver {
4692849878SLoGin     #[allow(dead_code)]
4745626c85SLoGin     pub fn early_scan_device_tree(&self) -> Result<(), SystemError> {
487a29d4fcSLoGin         let fdt_vaddr = boot_params().read().fdt().unwrap();
4945626c85SLoGin         let fdt = unsafe {
5045626c85SLoGin             fdt::Fdt::from_ptr(fdt_vaddr.as_ptr()).map_err(|e| {
5145626c85SLoGin                 kerror!("failed to parse fdt, err={:?}", e);
5245626c85SLoGin                 SystemError::EINVAL
5345626c85SLoGin             })
5445626c85SLoGin         }?;
5545626c85SLoGin 
5645626c85SLoGin         self.early_init_scan_nodes(&fdt);
5745626c85SLoGin 
5845626c85SLoGin         return Ok(());
5945626c85SLoGin     }
6045626c85SLoGin 
6145626c85SLoGin     fn early_init_scan_nodes(&self, fdt: &Fdt) {
6245626c85SLoGin         self.early_init_scan_root(fdt)
6345626c85SLoGin             .expect("Failed to scan fdt root node.");
6445626c85SLoGin 
6545626c85SLoGin         self.early_init_scan_chosen(fdt).unwrap_or_else(|_| {
6645626c85SLoGin             kwarn!("No `chosen` node found");
6745626c85SLoGin         });
6845626c85SLoGin 
6945626c85SLoGin         self.early_init_scan_memory(fdt);
7045626c85SLoGin     }
7145626c85SLoGin 
7245626c85SLoGin     /// 扫描根节点
7345626c85SLoGin     fn early_init_scan_root(&self, fdt: &Fdt) -> Result<(), SystemError> {
7445626c85SLoGin         let node = fdt.find_node("/").ok_or(SystemError::ENODEV)?;
7545626c85SLoGin 
7645626c85SLoGin         let mut guard = FDT_GLOBAL_DATA.write();
7745626c85SLoGin 
7845626c85SLoGin         if let Some(prop) = node.property("#size-cells") {
7945626c85SLoGin             guard.root_size_cells = prop.as_usize().unwrap() as u32;
8045626c85SLoGin 
81*453452ccSLoGin             // kdebug!("fdt_root_size_cells={}", guard.root_size_cells);
8245626c85SLoGin         }
8345626c85SLoGin 
8445626c85SLoGin         if let Some(prop) = node.property("#address-cells") {
8545626c85SLoGin             guard.root_addr_cells = prop.as_usize().unwrap() as u32;
8645626c85SLoGin 
87*453452ccSLoGin             // kdebug!("fdt_root_addr_cells={}", guard.root_addr_cells);
8845626c85SLoGin         }
8945626c85SLoGin 
9045626c85SLoGin         return Ok(());
9145626c85SLoGin     }
9245626c85SLoGin 
9345626c85SLoGin     /// 扫描 `/chosen` 节点
9445626c85SLoGin     fn early_init_scan_chosen(&self, fdt: &Fdt) -> Result<(), SystemError> {
9545626c85SLoGin         const CHOSEN_NAME1: &'static str = "/chosen";
9645626c85SLoGin         let mut node = fdt.find_node(CHOSEN_NAME1);
9745626c85SLoGin         if node.is_none() {
9845626c85SLoGin             const CHOSEN_NAME2: &'static str = "/chosen@0";
9945626c85SLoGin             node = fdt.find_node(CHOSEN_NAME2);
10045626c85SLoGin             if node.is_some() {
10145626c85SLoGin                 FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME2);
10245626c85SLoGin             }
10345626c85SLoGin         } else {
10445626c85SLoGin             FDT_GLOBAL_DATA.write().chosen_node_name = Some(CHOSEN_NAME1);
10545626c85SLoGin         }
10645626c85SLoGin 
10745626c85SLoGin         if let Some(node) = node {
10845626c85SLoGin             if let Some(prop) = node.property("bootargs") {
10945626c85SLoGin                 let bootargs = prop.as_str().unwrap();
11045626c85SLoGin 
11145626c85SLoGin                 boot_params()
11245626c85SLoGin                     .write()
11345626c85SLoGin                     .boot_cmdline_append(bootargs.as_bytes());
11445626c85SLoGin             }
11545626c85SLoGin         }
11645626c85SLoGin 
11745626c85SLoGin         // TODO: 拼接内核自定义的command line参数
11845626c85SLoGin 
11945626c85SLoGin         kdebug!("Command line: {}", boot_params().read().boot_cmdline_str());
12045626c85SLoGin         return Ok(());
12145626c85SLoGin     }
12245626c85SLoGin 
12345626c85SLoGin     /// 扫描 `/memory` 节点
12445626c85SLoGin     ///
12545626c85SLoGin     /// ## 参数
12645626c85SLoGin     ///
12745626c85SLoGin     /// - `fdt`:FDT
12845626c85SLoGin     ///
12945626c85SLoGin     /// ## 返回值
13045626c85SLoGin     ///
13145626c85SLoGin     /// 如果扫描成功,找到可用内存,则返回`true`,否则返回`false`。
13245626c85SLoGin     fn early_init_scan_memory(&self, fdt: &Fdt) -> bool {
13345626c85SLoGin         let mut found_memory = false;
13445626c85SLoGin         for node in fdt.all_nodes() {
13545626c85SLoGin             let device_type: Option<NodeProperty<'_>> = node.property("device_type");
13645626c85SLoGin             if device_type.is_none() {
13745626c85SLoGin                 continue;
13845626c85SLoGin             }
13945626c85SLoGin             let device_type = device_type.unwrap().as_str();
14045626c85SLoGin             if device_type.is_none() || device_type.unwrap() != "memory" {
14145626c85SLoGin                 continue;
14245626c85SLoGin             }
14345626c85SLoGin 
14445626c85SLoGin             if !self.is_device_avaliable(&node) {
14545626c85SLoGin                 continue;
14645626c85SLoGin             }
14745626c85SLoGin 
14845626c85SLoGin             let reg = node.property("reg");
14945626c85SLoGin             if reg.is_none() {
15045626c85SLoGin                 continue;
15145626c85SLoGin             }
15245626c85SLoGin             let reg = reg.unwrap();
15345626c85SLoGin             // 每个cell是4字节
15445626c85SLoGin             let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
15545626c85SLoGin             let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
15645626c85SLoGin 
15745626c85SLoGin             let total_elements_in_reg = reg.value.len() / ((addr_cells + size_cells) * 4);
15845626c85SLoGin 
15945626c85SLoGin             for i in 0..total_elements_in_reg {
160*453452ccSLoGin                 let base_index = i * (addr_cells + size_cells);
16145626c85SLoGin 
162*453452ccSLoGin                 let (base, base_index) = read_cell(reg.value, base_index, addr_cells);
163*453452ccSLoGin                 let (size, _) = read_cell(reg.value, base_index, size_cells);
16445626c85SLoGin 
16545626c85SLoGin                 if size == 0 {
16645626c85SLoGin                     continue;
16745626c85SLoGin                 }
16845626c85SLoGin 
16945626c85SLoGin                 kdebug!("Found memory: base={:#x}, size={:#x}", base, size);
17045626c85SLoGin                 self.early_init_dt_add_memory(base, size);
17145626c85SLoGin                 found_memory = true;
17245626c85SLoGin             }
17345626c85SLoGin         }
17445626c85SLoGin 
17545626c85SLoGin         return found_memory;
17645626c85SLoGin     }
17745626c85SLoGin 
17892849878SLoGin     #[cfg(target_arch = "x86_64")]
17992849878SLoGin     pub fn early_init_dt_add_memory(&self, _base: u64, _size: u64) {
18092849878SLoGin         kBUG!("x86_64 should not call early_init_dt_add_memory");
18192849878SLoGin     }
18292849878SLoGin 
18392849878SLoGin     #[cfg(not(target_arch = "x86_64"))]
18492849878SLoGin     pub fn early_init_dt_add_memory(&self, base: u64, size: u64) {
18592849878SLoGin         use crate::{
18692849878SLoGin             arch::MMArch,
18792849878SLoGin             libs::align::page_align_down,
18892849878SLoGin             mm::{
18992849878SLoGin                 memblock::{mem_block_manager, MemBlockManager},
19092849878SLoGin                 MemoryManagementArch, PhysAddr,
19192849878SLoGin             },
19292849878SLoGin         };
19392849878SLoGin 
19445626c85SLoGin         let mut base = base as usize;
19545626c85SLoGin         let mut size = size as usize;
19645626c85SLoGin 
19745626c85SLoGin         if size < (MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK))) {
19845626c85SLoGin             kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
19945626c85SLoGin         }
20045626c85SLoGin 
20145626c85SLoGin         if PhysAddr::new(base).check_aligned(MMArch::PAGE_SIZE) == false {
20245626c85SLoGin             size -= MMArch::PAGE_SIZE - (base & (!MMArch::PAGE_MASK));
20345626c85SLoGin             base = page_align_down(base);
20445626c85SLoGin         }
20545626c85SLoGin 
20645626c85SLoGin         size = page_align_down(size);
20745626c85SLoGin 
20845626c85SLoGin         if base > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
20945626c85SLoGin             kwarn!("Ignoring memory block {:#x}-{:#x}", base, base + size);
21045626c85SLoGin         }
21145626c85SLoGin 
21245626c85SLoGin         if base + size - 1 > MemBlockManager::MAX_MEMBLOCK_ADDR.data() {
21345626c85SLoGin             kwarn!(
21445626c85SLoGin                 "Ignoring memory range {:#x}-{:#x}",
21545626c85SLoGin                 MemBlockManager::MAX_MEMBLOCK_ADDR.data() + 1,
21645626c85SLoGin                 base + size
21745626c85SLoGin             );
21845626c85SLoGin             size = MemBlockManager::MAX_MEMBLOCK_ADDR.data() - base + 1;
21945626c85SLoGin         }
22045626c85SLoGin 
22145626c85SLoGin         if base + size < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
22245626c85SLoGin             kwarn!("Ignoring memory range {:#x}-{:#x}", base, base + size);
22345626c85SLoGin             return;
22445626c85SLoGin         }
22545626c85SLoGin 
22645626c85SLoGin         if base < MemBlockManager::MIN_MEMBLOCK_ADDR.data() {
22745626c85SLoGin             {
22845626c85SLoGin                 kwarn!(
22945626c85SLoGin                     "Ignoring memory range {:#x}-{:#x}",
23045626c85SLoGin                     base,
23145626c85SLoGin                     MemBlockManager::MIN_MEMBLOCK_ADDR.data()
23245626c85SLoGin                 );
23345626c85SLoGin                 size -= MemBlockManager::MIN_MEMBLOCK_ADDR.data() - base;
23445626c85SLoGin                 base = MemBlockManager::MIN_MEMBLOCK_ADDR.data();
23545626c85SLoGin             }
236*453452ccSLoGin         }
23745626c85SLoGin 
23845626c85SLoGin         mem_block_manager()
23945626c85SLoGin             .add_block(PhysAddr::new(base), size)
24045626c85SLoGin             .unwrap_or_else(|e| {
24145626c85SLoGin                 panic!(
24245626c85SLoGin                     "Failed to add memory block '{:#x}-{:#x}', err={:?}",
24345626c85SLoGin                     base,
24445626c85SLoGin                     base + size,
24545626c85SLoGin                     e
24645626c85SLoGin                 );
24745626c85SLoGin             });
24845626c85SLoGin     }
24945626c85SLoGin 
250*453452ccSLoGin     /// 判断设备是否可用
25145626c85SLoGin     fn is_device_avaliable(&self, node: &FdtNode) -> bool {
25245626c85SLoGin         let status = node.property("status");
25345626c85SLoGin         if status.is_none() {
25445626c85SLoGin             return true;
25545626c85SLoGin         }
25645626c85SLoGin 
25745626c85SLoGin         let status = status.unwrap().as_str();
25845626c85SLoGin         if let Some(status) = status {
25945626c85SLoGin             if status == "okay" || status == "ok" {
26045626c85SLoGin                 return true;
26145626c85SLoGin             }
26245626c85SLoGin         }
26345626c85SLoGin 
26445626c85SLoGin         return false;
26545626c85SLoGin     }
266*453452ccSLoGin 
267*453452ccSLoGin     /// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存
268*453452ccSLoGin     ///
269*453452ccSLoGin     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634
270*453452ccSLoGin     pub fn early_init_fdt_scan_reserved_mem(&self) {
271*453452ccSLoGin         let vaddr = boot_params().read().fdt();
272*453452ccSLoGin         if vaddr.is_none() {
273*453452ccSLoGin             return;
274*453452ccSLoGin         }
275*453452ccSLoGin         let vaddr = vaddr.unwrap();
276*453452ccSLoGin         let fdt = unsafe { Fdt::from_ptr(vaddr.data() as *const u8) };
277*453452ccSLoGin         if fdt.is_err() {
278*453452ccSLoGin             return;
279*453452ccSLoGin         }
280*453452ccSLoGin 
281*453452ccSLoGin         let fdt = fdt.unwrap();
282*453452ccSLoGin         self.early_reserve_fdt_itself(&fdt);
283*453452ccSLoGin 
284*453452ccSLoGin         let reserved_mem_nodes = fdt.memory_reservations();
285*453452ccSLoGin 
286*453452ccSLoGin         for node in reserved_mem_nodes {
287*453452ccSLoGin             if node.size() != 0 {
288*453452ccSLoGin                 let address = PhysAddr::new(node.address() as usize);
289*453452ccSLoGin                 let size = node.size();
290*453452ccSLoGin                 kdebug!("Reserve memory: {:?}-{:?}", address, address + size);
291*453452ccSLoGin                 mem_block_manager().reserve_block(address, size).unwrap();
292*453452ccSLoGin             }
293*453452ccSLoGin         }
294*453452ccSLoGin 
295*453452ccSLoGin         self.fdt_scan_reserved_mem(&fdt)
296*453452ccSLoGin             .expect("Failed to scan reserved memory");
297*453452ccSLoGin     }
298*453452ccSLoGin 
299*453452ccSLoGin     /// 保留fdt自身的内存空间
300*453452ccSLoGin 
301*453452ccSLoGin     fn early_reserve_fdt_itself(&self, fdt: &Fdt) {
302*453452ccSLoGin         #[cfg(target_arch = "riscv64")]
303*453452ccSLoGin         {
304*453452ccSLoGin             use crate::libs::align::{page_align_down, page_align_up};
305*453452ccSLoGin 
306*453452ccSLoGin             let fdt_paddr = boot_params().read().arch.fdt_paddr;
307*453452ccSLoGin             let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data()));
308*453452ccSLoGin             let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size());
309*453452ccSLoGin             mem_block_manager()
310*453452ccSLoGin                 .reserve_block(rsvd_start, rsvd_size)
311*453452ccSLoGin                 .expect("Failed to reserve memory for fdt");
312*453452ccSLoGin         }
313*453452ccSLoGin 
314*453452ccSLoGin         #[cfg(target_arch = "x86_64")]
315*453452ccSLoGin         {
316*453452ccSLoGin             let _ = fdt;
317*453452ccSLoGin         }
318*453452ccSLoGin     }
319*453452ccSLoGin 
320*453452ccSLoGin     fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> {
321*453452ccSLoGin         let node = fdt
322*453452ccSLoGin             .find_node("/reserved-memory")
323*453452ccSLoGin             .ok_or(SystemError::ENODEV)?;
324*453452ccSLoGin 
325*453452ccSLoGin         for child in node.children() {
326*453452ccSLoGin             if !self.is_device_avaliable(&child) {
327*453452ccSLoGin                 continue;
328*453452ccSLoGin             }
329*453452ccSLoGin 
330*453452ccSLoGin             reserved_mem_reserve_reg(&child).ok();
331*453452ccSLoGin         }
332*453452ccSLoGin 
333*453452ccSLoGin         return Ok(());
334*453452ccSLoGin     }
335*453452ccSLoGin 
336*453452ccSLoGin     fn early_init_dt_reserve_memory(
337*453452ccSLoGin         &self,
338*453452ccSLoGin         base: PhysAddr,
339*453452ccSLoGin         size: usize,
340*453452ccSLoGin         nomap: bool,
341*453452ccSLoGin     ) -> Result<(), SystemError> {
342*453452ccSLoGin         if nomap {
343*453452ccSLoGin             if mem_block_manager().is_overlapped(base, size)
344*453452ccSLoGin                 && mem_block_manager().is_overlapped_with_reserved(base, size)
345*453452ccSLoGin             {
346*453452ccSLoGin                 // 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`,
347*453452ccSLoGin                 // 但是不需要担心如果该区域不是内存(即不会被映射)的情况。
348*453452ccSLoGin                 return Err(SystemError::EBUSY);
349*453452ccSLoGin             }
350*453452ccSLoGin 
351*453452ccSLoGin             return mem_block_manager().mark_nomap(base, size);
352*453452ccSLoGin         }
353*453452ccSLoGin 
354*453452ccSLoGin         return mem_block_manager().reserve_block(base, size);
355*453452ccSLoGin     }
356*453452ccSLoGin }
357*453452ccSLoGin 
358*453452ccSLoGin #[allow(dead_code)]
359*453452ccSLoGin fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> {
360*453452ccSLoGin     let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> =
361*453452ccSLoGin         FDT_GLOBAL_DATA.read();
362*453452ccSLoGin     let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize)
363*453452ccSLoGin         * size_of::<u32>();
364*453452ccSLoGin     drop(global_data_guard);
365*453452ccSLoGin 
366*453452ccSLoGin     let reg = node.property("reg").ok_or(SystemError::ENOENT)?;
367*453452ccSLoGin 
368*453452ccSLoGin     let mut reg_size = reg.value.len();
369*453452ccSLoGin     if reg_size > 0 && reg_size % t_len != 0 {
370*453452ccSLoGin         kerror!(
371*453452ccSLoGin             "Reserved memory: invalid reg property in '{}', skipping node.",
372*453452ccSLoGin             node.name
373*453452ccSLoGin         );
374*453452ccSLoGin         return Err(SystemError::EINVAL);
375*453452ccSLoGin     }
376*453452ccSLoGin     // 每个cell是4字节
377*453452ccSLoGin     let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
378*453452ccSLoGin     let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
379*453452ccSLoGin 
380*453452ccSLoGin     let nomap = node.property("no-map").is_some();
381*453452ccSLoGin 
382*453452ccSLoGin     let mut base_index = 0;
383*453452ccSLoGin 
384*453452ccSLoGin     while reg_size >= t_len {
385*453452ccSLoGin         let (base, bi) = read_cell(reg.value, base_index, addr_cells);
386*453452ccSLoGin         base_index = bi;
387*453452ccSLoGin         let (size, bi) = read_cell(reg.value, base_index, size_cells);
388*453452ccSLoGin         base_index = bi;
389*453452ccSLoGin 
390*453452ccSLoGin         if size > 0
391*453452ccSLoGin             && open_firmware_fdt_driver()
392*453452ccSLoGin                 .early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap)
393*453452ccSLoGin                 .is_ok()
394*453452ccSLoGin         {
395*453452ccSLoGin             kdebug!(
396*453452ccSLoGin                 "Reserved memory: base={:#x}, size={:#x}, nomap={}",
397*453452ccSLoGin                 base,
398*453452ccSLoGin                 size,
399*453452ccSLoGin                 nomap
400*453452ccSLoGin             );
401*453452ccSLoGin         } else {
402*453452ccSLoGin             kerror!(
403*453452ccSLoGin                 "Failed to reserve memory: base={:#x}, size={:#x}, nomap={}",
404*453452ccSLoGin                 base,
405*453452ccSLoGin                 size,
406*453452ccSLoGin                 nomap
407*453452ccSLoGin             );
408*453452ccSLoGin         }
409*453452ccSLoGin 
410*453452ccSLoGin         reg_size -= t_len;
411*453452ccSLoGin 
412*453452ccSLoGin         // todo: linux这里保存了节点,但是我感觉现在还用不着。
413*453452ccSLoGin     }
414*453452ccSLoGin 
415*453452ccSLoGin     return Ok(());
416*453452ccSLoGin }
417*453452ccSLoGin 
418*453452ccSLoGin /// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回
419*453452ccSLoGin ///
420*453452ccSLoGin /// ## 参数
421*453452ccSLoGin ///
422*453452ccSLoGin /// - `reg_value`:`reg`属性数组的引用
423*453452ccSLoGin /// - `base_index`:起始索引
424*453452ccSLoGin /// - `cells`:要读取的cell数量,必须是1或2
425*453452ccSLoGin ///
426*453452ccSLoGin /// ## 返回值
427*453452ccSLoGin ///
428*453452ccSLoGin /// (value, next_base_index)
429*453452ccSLoGin fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) {
430*453452ccSLoGin     let next_base_index = base_index + cells * 4;
431*453452ccSLoGin     match cells {
432*453452ccSLoGin         1 => {
433*453452ccSLoGin             return (
434*453452ccSLoGin                 u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap())
435*453452ccSLoGin                     .try_into()
436*453452ccSLoGin                     .unwrap(),
437*453452ccSLoGin                 next_base_index,
438*453452ccSLoGin             );
439*453452ccSLoGin         }
440*453452ccSLoGin 
441*453452ccSLoGin         2 => {
442*453452ccSLoGin             return (
443*453452ccSLoGin                 u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()),
444*453452ccSLoGin                 next_base_index,
445*453452ccSLoGin             );
446*453452ccSLoGin         }
447*453452ccSLoGin         _ => {
448*453452ccSLoGin             panic!("cells must be 1 or 2");
449*453452ccSLoGin         }
450*453452ccSLoGin     }
45145626c85SLoGin }
452