xref: /DragonOS/kernel/src/driver/open_firmware/fdt.rs (revision b5b571e02693d91eb6918d3b7561e088c3e7ee81)
1453452ccSLoGin use core::mem::size_of;
2453452ccSLoGin 
345626c85SLoGin use fdt::{
445626c85SLoGin     node::{FdtNode, NodeProperty},
545626c85SLoGin     Fdt,
645626c85SLoGin };
745626c85SLoGin use system_error::SystemError;
845626c85SLoGin 
9453452ccSLoGin use crate::{
10453452ccSLoGin     init::boot_params,
11453452ccSLoGin     libs::rwlock::RwLock,
12453452ccSLoGin     mm::{memblock::mem_block_manager, PhysAddr},
13453452ccSLoGin };
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 
81453452ccSLoGin             // 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 
87453452ccSLoGin             // 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> {
95*b5b571e0SLoGin         const CHOSEN_NAME1: &str = "/chosen";
9645626c85SLoGin         let mut node = fdt.find_node(CHOSEN_NAME1);
9745626c85SLoGin         if node.is_none() {
98*b5b571e0SLoGin             const CHOSEN_NAME2: &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 {
160453452ccSLoGin                 let base_index = i * (addr_cells + size_cells);
16145626c85SLoGin 
162453452ccSLoGin                 let (base, base_index) = read_cell(reg.value, base_index, addr_cells);
163453452ccSLoGin                 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             }
236453452ccSLoGin         }
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 
250453452ccSLoGin     /// 判断设备是否可用
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     }
266453452ccSLoGin 
267453452ccSLoGin     /// 在UEFI初始化后,扫描FDT中的`/reserved-memory`节点,设置保留的内存
268453452ccSLoGin     ///
269453452ccSLoGin     /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/of/fdt.c#634
270453452ccSLoGin     pub fn early_init_fdt_scan_reserved_mem(&self) {
271453452ccSLoGin         let vaddr = boot_params().read().fdt();
272453452ccSLoGin         if vaddr.is_none() {
273453452ccSLoGin             return;
274453452ccSLoGin         }
275453452ccSLoGin         let vaddr = vaddr.unwrap();
276453452ccSLoGin         let fdt = unsafe { Fdt::from_ptr(vaddr.data() as *const u8) };
277453452ccSLoGin         if fdt.is_err() {
278453452ccSLoGin             return;
279453452ccSLoGin         }
280453452ccSLoGin 
281453452ccSLoGin         let fdt = fdt.unwrap();
282453452ccSLoGin         self.early_reserve_fdt_itself(&fdt);
283453452ccSLoGin 
284453452ccSLoGin         let reserved_mem_nodes = fdt.memory_reservations();
285453452ccSLoGin 
286453452ccSLoGin         for node in reserved_mem_nodes {
287453452ccSLoGin             if node.size() != 0 {
288453452ccSLoGin                 let address = PhysAddr::new(node.address() as usize);
289453452ccSLoGin                 let size = node.size();
290453452ccSLoGin                 kdebug!("Reserve memory: {:?}-{:?}", address, address + size);
291453452ccSLoGin                 mem_block_manager().reserve_block(address, size).unwrap();
292453452ccSLoGin             }
293453452ccSLoGin         }
294453452ccSLoGin 
295453452ccSLoGin         self.fdt_scan_reserved_mem(&fdt)
296453452ccSLoGin             .expect("Failed to scan reserved memory");
297453452ccSLoGin     }
298453452ccSLoGin 
299453452ccSLoGin     /// 保留fdt自身的内存空间
300453452ccSLoGin 
301453452ccSLoGin     fn early_reserve_fdt_itself(&self, fdt: &Fdt) {
302453452ccSLoGin         #[cfg(target_arch = "riscv64")]
303453452ccSLoGin         {
304453452ccSLoGin             use crate::libs::align::{page_align_down, page_align_up};
305453452ccSLoGin 
306453452ccSLoGin             let fdt_paddr = boot_params().read().arch.fdt_paddr;
307453452ccSLoGin             let rsvd_start = PhysAddr::new(page_align_down(fdt_paddr.data()));
308453452ccSLoGin             let rsvd_size = page_align_up(fdt_paddr.data() - rsvd_start.data() + fdt.total_size());
309453452ccSLoGin             mem_block_manager()
310453452ccSLoGin                 .reserve_block(rsvd_start, rsvd_size)
311453452ccSLoGin                 .expect("Failed to reserve memory for fdt");
312453452ccSLoGin         }
313453452ccSLoGin 
314453452ccSLoGin         #[cfg(target_arch = "x86_64")]
315453452ccSLoGin         {
316453452ccSLoGin             let _ = fdt;
317453452ccSLoGin         }
318453452ccSLoGin     }
319453452ccSLoGin 
320453452ccSLoGin     fn fdt_scan_reserved_mem(&self, fdt: &Fdt) -> Result<(), SystemError> {
321453452ccSLoGin         let node = fdt
322453452ccSLoGin             .find_node("/reserved-memory")
323453452ccSLoGin             .ok_or(SystemError::ENODEV)?;
324453452ccSLoGin 
325453452ccSLoGin         for child in node.children() {
326453452ccSLoGin             if !self.is_device_avaliable(&child) {
327453452ccSLoGin                 continue;
328453452ccSLoGin             }
329453452ccSLoGin 
330453452ccSLoGin             reserved_mem_reserve_reg(&child).ok();
331453452ccSLoGin         }
332453452ccSLoGin 
333453452ccSLoGin         return Ok(());
334453452ccSLoGin     }
335453452ccSLoGin 
336453452ccSLoGin     fn early_init_dt_reserve_memory(
337453452ccSLoGin         &self,
338453452ccSLoGin         base: PhysAddr,
339453452ccSLoGin         size: usize,
340453452ccSLoGin         nomap: bool,
341453452ccSLoGin     ) -> Result<(), SystemError> {
342453452ccSLoGin         if nomap {
343453452ccSLoGin             if mem_block_manager().is_overlapped(base, size)
344453452ccSLoGin                 && mem_block_manager().is_overlapped_with_reserved(base, size)
345453452ccSLoGin             {
346453452ccSLoGin                 // 如果内存已经被其他区域预留(即已经被映射),我们不应该允许它被标记为`nomap`,
347453452ccSLoGin                 // 但是不需要担心如果该区域不是内存(即不会被映射)的情况。
348453452ccSLoGin                 return Err(SystemError::EBUSY);
349453452ccSLoGin             }
350453452ccSLoGin 
351453452ccSLoGin             return mem_block_manager().mark_nomap(base, size);
352453452ccSLoGin         }
353453452ccSLoGin 
354453452ccSLoGin         return mem_block_manager().reserve_block(base, size);
355453452ccSLoGin     }
356453452ccSLoGin }
357453452ccSLoGin 
358453452ccSLoGin #[allow(dead_code)]
359453452ccSLoGin fn reserved_mem_reserve_reg(node: &FdtNode<'_, '_>) -> Result<(), SystemError> {
360453452ccSLoGin     let global_data_guard: crate::libs::rwlock::RwLockReadGuard<'_, FdtGlobalData> =
361453452ccSLoGin         FDT_GLOBAL_DATA.read();
362453452ccSLoGin     let t_len = ((global_data_guard.root_addr_cells + global_data_guard.root_size_cells) as usize)
363453452ccSLoGin         * size_of::<u32>();
364453452ccSLoGin     drop(global_data_guard);
365453452ccSLoGin 
366453452ccSLoGin     let reg = node.property("reg").ok_or(SystemError::ENOENT)?;
367453452ccSLoGin 
368453452ccSLoGin     let mut reg_size = reg.value.len();
369453452ccSLoGin     if reg_size > 0 && reg_size % t_len != 0 {
370453452ccSLoGin         kerror!(
371453452ccSLoGin             "Reserved memory: invalid reg property in '{}', skipping node.",
372453452ccSLoGin             node.name
373453452ccSLoGin         );
374453452ccSLoGin         return Err(SystemError::EINVAL);
375453452ccSLoGin     }
376453452ccSLoGin     // 每个cell是4字节
377453452ccSLoGin     let addr_cells = FDT_GLOBAL_DATA.read().root_addr_cells as usize;
378453452ccSLoGin     let size_cells = FDT_GLOBAL_DATA.read().root_size_cells as usize;
379453452ccSLoGin 
380453452ccSLoGin     let nomap = node.property("no-map").is_some();
381453452ccSLoGin 
382453452ccSLoGin     let mut base_index = 0;
383453452ccSLoGin 
384453452ccSLoGin     while reg_size >= t_len {
385453452ccSLoGin         let (base, bi) = read_cell(reg.value, base_index, addr_cells);
386453452ccSLoGin         base_index = bi;
387453452ccSLoGin         let (size, bi) = read_cell(reg.value, base_index, size_cells);
388453452ccSLoGin         base_index = bi;
389453452ccSLoGin 
390453452ccSLoGin         if size > 0
391453452ccSLoGin             && open_firmware_fdt_driver()
392453452ccSLoGin                 .early_init_dt_reserve_memory(PhysAddr::new(base as usize), size as usize, nomap)
393453452ccSLoGin                 .is_ok()
394453452ccSLoGin         {
395453452ccSLoGin             kdebug!(
396453452ccSLoGin                 "Reserved memory: base={:#x}, size={:#x}, nomap={}",
397453452ccSLoGin                 base,
398453452ccSLoGin                 size,
399453452ccSLoGin                 nomap
400453452ccSLoGin             );
401453452ccSLoGin         } else {
402453452ccSLoGin             kerror!(
403453452ccSLoGin                 "Failed to reserve memory: base={:#x}, size={:#x}, nomap={}",
404453452ccSLoGin                 base,
405453452ccSLoGin                 size,
406453452ccSLoGin                 nomap
407453452ccSLoGin             );
408453452ccSLoGin         }
409453452ccSLoGin 
410453452ccSLoGin         reg_size -= t_len;
411453452ccSLoGin 
412453452ccSLoGin         // todo: linux这里保存了节点,但是我感觉现在还用不着。
413453452ccSLoGin     }
414453452ccSLoGin 
415453452ccSLoGin     return Ok(());
416453452ccSLoGin }
417453452ccSLoGin 
418453452ccSLoGin /// 从FDT的`reg`属性中读取指定数量的cell,作为一个小端u64返回
419453452ccSLoGin ///
420453452ccSLoGin /// ## 参数
421453452ccSLoGin ///
422453452ccSLoGin /// - `reg_value`:`reg`属性数组的引用
423453452ccSLoGin /// - `base_index`:起始索引
424453452ccSLoGin /// - `cells`:要读取的cell数量,必须是1或2
425453452ccSLoGin ///
426453452ccSLoGin /// ## 返回值
427453452ccSLoGin ///
428453452ccSLoGin /// (value, next_base_index)
429453452ccSLoGin fn read_cell(reg_value: &[u8], base_index: usize, cells: usize) -> (u64, usize) {
430453452ccSLoGin     let next_base_index = base_index + cells * 4;
431453452ccSLoGin     match cells {
432453452ccSLoGin         1 => {
433453452ccSLoGin             return (
434453452ccSLoGin                 u32::from_be_bytes(reg_value[base_index..base_index + 4].try_into().unwrap())
435453452ccSLoGin                     .try_into()
436453452ccSLoGin                     .unwrap(),
437453452ccSLoGin                 next_base_index,
438453452ccSLoGin             );
439453452ccSLoGin         }
440453452ccSLoGin 
441453452ccSLoGin         2 => {
442453452ccSLoGin             return (
443453452ccSLoGin                 u64::from_be_bytes(reg_value[base_index..base_index + 8].try_into().unwrap()),
444453452ccSLoGin                 next_base_index,
445453452ccSLoGin             );
446453452ccSLoGin         }
447453452ccSLoGin         _ => {
448453452ccSLoGin             panic!("cells must be 1 or 2");
449453452ccSLoGin         }
450453452ccSLoGin     }
45145626c85SLoGin }
452