xref: /aosp_15_r20/bootable/libbootloader/gbl/efi/src/fuchsia_boot.rs (revision 5225e6b173e52d2efc6bcf950c27374fd72adabc)
1*5225e6b1SAndroid Build Coastguard Worker // Copyright 2024, The Android Open Source Project
2*5225e6b1SAndroid Build Coastguard Worker //
3*5225e6b1SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*5225e6b1SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*5225e6b1SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*5225e6b1SAndroid Build Coastguard Worker //
7*5225e6b1SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*5225e6b1SAndroid Build Coastguard Worker //
9*5225e6b1SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*5225e6b1SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*5225e6b1SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5225e6b1SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*5225e6b1SAndroid Build Coastguard Worker // limitations under the License.
14*5225e6b1SAndroid Build Coastguard Worker 
15*5225e6b1SAndroid Build Coastguard Worker use crate::utils::efi_to_zbi_mem_range_type;
16*5225e6b1SAndroid Build Coastguard Worker #[allow(unused_imports)]
17*5225e6b1SAndroid Build Coastguard Worker use crate::{
18*5225e6b1SAndroid Build Coastguard Worker     efi_blocks::find_block_devices, fastboot::fastboot, ops::Ops, utils::get_efi_mem_attr,
19*5225e6b1SAndroid Build Coastguard Worker };
20*5225e6b1SAndroid Build Coastguard Worker use core::fmt::Write;
21*5225e6b1SAndroid Build Coastguard Worker use efi::{efi_print, efi_println, EfiEntry, EfiMemoryAttributesTable, EfiMemoryMap};
22*5225e6b1SAndroid Build Coastguard Worker use efi_types::{
23*5225e6b1SAndroid Build Coastguard Worker     EfiMemoryAttributesTableHeader, EfiMemoryDescriptor, EFI_MEMORY_ATTRIBUTE_EMA_RUNTIME,
24*5225e6b1SAndroid Build Coastguard Worker };
25*5225e6b1SAndroid Build Coastguard Worker use liberror::Error;
26*5225e6b1SAndroid Build Coastguard Worker use liberror::Error::BufferTooSmall;
27*5225e6b1SAndroid Build Coastguard Worker use libgbl::{
28*5225e6b1SAndroid Build Coastguard Worker     fuchsia_boot::{zircon_check_enter_fastboot, zircon_load_verify_abr, zircon_part_name},
29*5225e6b1SAndroid Build Coastguard Worker     partition::check_part_unique,
30*5225e6b1SAndroid Build Coastguard Worker     IntegrationError::UnificationError,
31*5225e6b1SAndroid Build Coastguard Worker     Os, Result,
32*5225e6b1SAndroid Build Coastguard Worker };
33*5225e6b1SAndroid Build Coastguard Worker use safemath::SafeNum;
34*5225e6b1SAndroid Build Coastguard Worker use zbi::{zbi_format::zbi_mem_range_t, ZbiContainer, ZbiFlags, ZbiType};
35*5225e6b1SAndroid Build Coastguard Worker use zerocopy::{ByteSliceMut, Ref};
36*5225e6b1SAndroid Build Coastguard Worker 
37*5225e6b1SAndroid Build Coastguard Worker const PAGE_SIZE: u64 = 4096;
38*5225e6b1SAndroid Build Coastguard Worker 
39*5225e6b1SAndroid Build Coastguard Worker /// Check if the disk GPT layout is a Fuchsia device layout.
is_fuchsia_gpt(efi_entry: &EfiEntry) -> Result<()>40*5225e6b1SAndroid Build Coastguard Worker pub fn is_fuchsia_gpt(efi_entry: &EfiEntry) -> Result<()> {
41*5225e6b1SAndroid Build Coastguard Worker     let gpt_devices = find_block_devices(&efi_entry)?;
42*5225e6b1SAndroid Build Coastguard Worker     let partitions: &[&[&str]] = &[
43*5225e6b1SAndroid Build Coastguard Worker         &["zircon_a", "zircon-a"],
44*5225e6b1SAndroid Build Coastguard Worker         &["zircon_b", "zircon-b"],
45*5225e6b1SAndroid Build Coastguard Worker         &["zircon_r", "zircon-r"],
46*5225e6b1SAndroid Build Coastguard Worker         &["vbmeta_a"],
47*5225e6b1SAndroid Build Coastguard Worker         &["vbmeta_b"],
48*5225e6b1SAndroid Build Coastguard Worker         &["vbmeta_r"],
49*5225e6b1SAndroid Build Coastguard Worker         &["misc", "durable_boot"],
50*5225e6b1SAndroid Build Coastguard Worker     ];
51*5225e6b1SAndroid Build Coastguard Worker     if !partitions
52*5225e6b1SAndroid Build Coastguard Worker         .iter()
53*5225e6b1SAndroid Build Coastguard Worker         .all(|&partition| partition.iter().any(|v| check_part_unique(&gpt_devices[..], *v).is_ok()))
54*5225e6b1SAndroid Build Coastguard Worker     {
55*5225e6b1SAndroid Build Coastguard Worker         return Err(Error::NotFound.into());
56*5225e6b1SAndroid Build Coastguard Worker     }
57*5225e6b1SAndroid Build Coastguard Worker 
58*5225e6b1SAndroid Build Coastguard Worker     Ok(())
59*5225e6b1SAndroid Build Coastguard Worker }
60*5225e6b1SAndroid Build Coastguard Worker 
61*5225e6b1SAndroid Build Coastguard Worker /// Loads, verifies and boots Fuchsia according to A/B/R.
fuchsia_boot_demo(efi_entry: EfiEntry) -> Result<()>62*5225e6b1SAndroid Build Coastguard Worker pub fn fuchsia_boot_demo(efi_entry: EfiEntry) -> Result<()> {
63*5225e6b1SAndroid Build Coastguard Worker     efi_println!(efi_entry, "Try booting as Fuchsia/Zircon");
64*5225e6b1SAndroid Build Coastguard Worker 
65*5225e6b1SAndroid Build Coastguard Worker     let (mut zbi_items_buffer, mut _kernel_buffer, slot) = {
66*5225e6b1SAndroid Build Coastguard Worker         let blks = find_block_devices(&efi_entry)?;
67*5225e6b1SAndroid Build Coastguard Worker         let mut ops = Ops::new(&efi_entry, &blks[..], Some(Os::Fuchsia));
68*5225e6b1SAndroid Build Coastguard Worker         // Checks whether to enter fastboot mode.
69*5225e6b1SAndroid Build Coastguard Worker         if zircon_check_enter_fastboot(&mut ops) {
70*5225e6b1SAndroid Build Coastguard Worker             fastboot(&mut ops, &mut [])?;
71*5225e6b1SAndroid Build Coastguard Worker         }
72*5225e6b1SAndroid Build Coastguard Worker         zircon_load_verify_abr(&mut ops)?
73*5225e6b1SAndroid Build Coastguard Worker     };
74*5225e6b1SAndroid Build Coastguard Worker     efi_println!(efi_entry, "Booting from slot: {}", zircon_part_name(Some(slot)));
75*5225e6b1SAndroid Build Coastguard Worker 
76*5225e6b1SAndroid Build Coastguard Worker     let _zbi_items = zbi_items_buffer.used_mut();
77*5225e6b1SAndroid Build Coastguard Worker 
78*5225e6b1SAndroid Build Coastguard Worker     #[cfg(target_arch = "aarch64")]
79*5225e6b1SAndroid Build Coastguard Worker     {
80*5225e6b1SAndroid Build Coastguard Worker         // Uses the unused buffer for `exit_boot_services` to store output memory map.
81*5225e6b1SAndroid Build Coastguard Worker         // The map is not used for now. We currently rely on UEFI firmware to pass memory map via
82*5225e6b1SAndroid Build Coastguard Worker         // an raw zbi blob in device tree. Long term we want to support adding from EFI memory maps
83*5225e6b1SAndroid Build Coastguard Worker         // if none is provided.
84*5225e6b1SAndroid Build Coastguard Worker         let item_size = zbi::ZbiContainer::parse(&mut _zbi_items[..])?.container_size()?;
85*5225e6b1SAndroid Build Coastguard Worker         let (_, remains) = _zbi_items.split_at_mut(item_size);
86*5225e6b1SAndroid Build Coastguard Worker         let _ = efi::exit_boot_services(efi_entry, remains).unwrap();
87*5225e6b1SAndroid Build Coastguard Worker         // SAFETY: The kernel has passed libavb verification or device is unlocked, in which case we
88*5225e6b1SAndroid Build Coastguard Worker         // assume the caller has addressed all safety and security concerns.
89*5225e6b1SAndroid Build Coastguard Worker         unsafe { boot::aarch64::jump_zircon_el2_or_lower(_kernel_buffer.used_mut(), _zbi_items) };
90*5225e6b1SAndroid Build Coastguard Worker     }
91*5225e6b1SAndroid Build Coastguard Worker 
92*5225e6b1SAndroid Build Coastguard Worker     #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
93*5225e6b1SAndroid Build Coastguard Worker     {
94*5225e6b1SAndroid Build Coastguard Worker         const BUFFER_SIZE: usize = 32 * 1024 / 2;
95*5225e6b1SAndroid Build Coastguard Worker         let mut mem_map_buf = [0u8; BUFFER_SIZE];
96*5225e6b1SAndroid Build Coastguard Worker         let mut zbi_items = zbi::ZbiContainer::parse(&mut _zbi_items[..])?;
97*5225e6b1SAndroid Build Coastguard Worker         let efi_memory_attribute_table = get_efi_mem_attr(&efi_entry).ok_or(Error::InvalidInput)?;
98*5225e6b1SAndroid Build Coastguard Worker 
99*5225e6b1SAndroid Build Coastguard Worker         // `exit_boot_service` returnes EFI memory map that is used to derive and append MEM_CONFIG
100*5225e6b1SAndroid Build Coastguard Worker         // items.
101*5225e6b1SAndroid Build Coastguard Worker         let efi_memory_map = efi::exit_boot_services(efi_entry, &mut mem_map_buf).unwrap();
102*5225e6b1SAndroid Build Coastguard Worker 
103*5225e6b1SAndroid Build Coastguard Worker         add_memory_items(&efi_memory_map, &efi_memory_attribute_table, &mut zbi_items)?;
104*5225e6b1SAndroid Build Coastguard Worker 
105*5225e6b1SAndroid Build Coastguard Worker         // SAFETY: The kernel has passed libavb verification or device is unlocked, in which case we
106*5225e6b1SAndroid Build Coastguard Worker         // assume the caller has addressed all safety and security concerns.
107*5225e6b1SAndroid Build Coastguard Worker         unsafe { boot::x86::zbi_boot(_kernel_buffer.used_mut(), _zbi_items) };
108*5225e6b1SAndroid Build Coastguard Worker     }
109*5225e6b1SAndroid Build Coastguard Worker 
110*5225e6b1SAndroid Build Coastguard Worker     #[cfg(target_arch = "riscv64")]
111*5225e6b1SAndroid Build Coastguard Worker     {
112*5225e6b1SAndroid Build Coastguard Worker         unimplemented!();
113*5225e6b1SAndroid Build Coastguard Worker     }
114*5225e6b1SAndroid Build Coastguard Worker }
115*5225e6b1SAndroid Build Coastguard Worker 
116*5225e6b1SAndroid Build Coastguard Worker // This function must not use allocation
117*5225e6b1SAndroid Build Coastguard Worker #[allow(unused)]
add_memory_items<B>( efi_memory_map: &EfiMemoryMap, efi_memory_attribute_table: &EfiMemoryAttributesTable, zbi_items: &mut ZbiContainer<B>, ) -> Result<()> where B: ByteSliceMut + PartialEq,118*5225e6b1SAndroid Build Coastguard Worker fn add_memory_items<B>(
119*5225e6b1SAndroid Build Coastguard Worker     efi_memory_map: &EfiMemoryMap,
120*5225e6b1SAndroid Build Coastguard Worker     efi_memory_attribute_table: &EfiMemoryAttributesTable,
121*5225e6b1SAndroid Build Coastguard Worker     zbi_items: &mut ZbiContainer<B>,
122*5225e6b1SAndroid Build Coastguard Worker ) -> Result<()>
123*5225e6b1SAndroid Build Coastguard Worker where
124*5225e6b1SAndroid Build Coastguard Worker     B: ByteSliceMut + PartialEq,
125*5225e6b1SAndroid Build Coastguard Worker {
126*5225e6b1SAndroid Build Coastguard Worker     generate_efi_memory_attributes_table_item(
127*5225e6b1SAndroid Build Coastguard Worker         efi_memory_map,
128*5225e6b1SAndroid Build Coastguard Worker         efi_memory_attribute_table,
129*5225e6b1SAndroid Build Coastguard Worker         zbi_items,
130*5225e6b1SAndroid Build Coastguard Worker     )?;
131*5225e6b1SAndroid Build Coastguard Worker 
132*5225e6b1SAndroid Build Coastguard Worker     generate_mem_config_item(efi_memory_map, zbi_items)?;
133*5225e6b1SAndroid Build Coastguard Worker 
134*5225e6b1SAndroid Build Coastguard Worker     Ok(())
135*5225e6b1SAndroid Build Coastguard Worker }
136*5225e6b1SAndroid Build Coastguard Worker 
generate_efi_memory_attributes_table_item<'b, B>( efi_memory_map: &EfiMemoryMap<'b>, efi_memory_attribute_table: &EfiMemoryAttributesTable, zbi_items: &mut ZbiContainer<B>, ) -> Result<()> where B: ByteSliceMut + PartialEq,137*5225e6b1SAndroid Build Coastguard Worker fn generate_efi_memory_attributes_table_item<'b, B>(
138*5225e6b1SAndroid Build Coastguard Worker     efi_memory_map: &EfiMemoryMap<'b>,
139*5225e6b1SAndroid Build Coastguard Worker     efi_memory_attribute_table: &EfiMemoryAttributesTable,
140*5225e6b1SAndroid Build Coastguard Worker     zbi_items: &mut ZbiContainer<B>,
141*5225e6b1SAndroid Build Coastguard Worker ) -> Result<()>
142*5225e6b1SAndroid Build Coastguard Worker where
143*5225e6b1SAndroid Build Coastguard Worker     B: ByteSliceMut + PartialEq,
144*5225e6b1SAndroid Build Coastguard Worker {
145*5225e6b1SAndroid Build Coastguard Worker     let payload = zbi_items.get_next_payload()?;
146*5225e6b1SAndroid Build Coastguard Worker     let provided_payload_size = payload.len();
147*5225e6b1SAndroid Build Coastguard Worker     let (mut header, mut tail) =
148*5225e6b1SAndroid Build Coastguard Worker         Ref::<&mut [u8], EfiMemoryAttributesTableHeader>::new_from_prefix(payload)
149*5225e6b1SAndroid Build Coastguard Worker             .ok_or(Error::BadBufferSize)?;
150*5225e6b1SAndroid Build Coastguard Worker 
151*5225e6b1SAndroid Build Coastguard Worker     for efi_memory_desc in efi_memory_map.into_iter() {
152*5225e6b1SAndroid Build Coastguard Worker         if efi_memory_desc.attributes & EFI_MEMORY_ATTRIBUTE_EMA_RUNTIME == 0 {
153*5225e6b1SAndroid Build Coastguard Worker             continue;
154*5225e6b1SAndroid Build Coastguard Worker         }
155*5225e6b1SAndroid Build Coastguard Worker 
156*5225e6b1SAndroid Build Coastguard Worker         let mut base = efi_memory_desc.physical_start;
157*5225e6b1SAndroid Build Coastguard Worker         let mut size: u64 = (SafeNum::from(efi_memory_desc.number_of_pages) * PAGE_SIZE)
158*5225e6b1SAndroid Build Coastguard Worker             .try_into()
159*5225e6b1SAndroid Build Coastguard Worker             .map_err(Error::from)?;
160*5225e6b1SAndroid Build Coastguard Worker 
161*5225e6b1SAndroid Build Coastguard Worker         // This EMAT entry is either a sub-region or a full copy of the memory map region, per
162*5225e6b1SAndroid Build Coastguard Worker         // EFI 2.10 4.6.4: "Additionally, every memory region described by a Descriptor in
163*5225e6b1SAndroid Build Coastguard Worker         // EFI_MEMORY_ATTRIBUTES_TABLE must be a sub-region of, or equal to, a descriptor in the
164*5225e6b1SAndroid Build Coastguard Worker         // table produced by GetMemoryMap()."
165*5225e6b1SAndroid Build Coastguard Worker         //
166*5225e6b1SAndroid Build Coastguard Worker         // This means that we do not have to consider the case where the EMAT entry only overlaps
167*5225e6b1SAndroid Build Coastguard Worker         // the end of the memory map entry.
168*5225e6b1SAndroid Build Coastguard Worker         //
169*5225e6b1SAndroid Build Coastguard Worker         // EMAT items are ordered by physical address, so once we go past |base| we can quit the
170*5225e6b1SAndroid Build Coastguard Worker         // loop.
171*5225e6b1SAndroid Build Coastguard Worker         for emat_item in efi_memory_attribute_table
172*5225e6b1SAndroid Build Coastguard Worker             .into_iter()
173*5225e6b1SAndroid Build Coastguard Worker             .skip_while(move |item| item.physical_start < base)
174*5225e6b1SAndroid Build Coastguard Worker             .take_while(move |item| item.physical_start < base + size)
175*5225e6b1SAndroid Build Coastguard Worker         {
176*5225e6b1SAndroid Build Coastguard Worker             if emat_item.physical_start > base {
177*5225e6b1SAndroid Build Coastguard Worker                 // Create a region for [base ... emat_item->PhysicalStart), because that region is
178*5225e6b1SAndroid Build Coastguard Worker                 // not covered by the EMAT.
179*5225e6b1SAndroid Build Coastguard Worker                 let mut generated_item;
180*5225e6b1SAndroid Build Coastguard Worker                 (generated_item, tail) = Ref::<_, EfiMemoryDescriptor>::new_from_prefix(tail)
181*5225e6b1SAndroid Build Coastguard Worker                     .ok_or(UnificationError(BufferTooSmall(Some(
182*5225e6b1SAndroid Build Coastguard Worker                         size_of::<EfiMemoryDescriptor>(),
183*5225e6b1SAndroid Build Coastguard Worker                     ))))?;
184*5225e6b1SAndroid Build Coastguard Worker 
185*5225e6b1SAndroid Build Coastguard Worker                 generated_item.physical_start = base;
186*5225e6b1SAndroid Build Coastguard Worker                 generated_item.number_of_pages = (emat_item.physical_start - base) / PAGE_SIZE;
187*5225e6b1SAndroid Build Coastguard Worker                 generated_item.virtual_start = 0;
188*5225e6b1SAndroid Build Coastguard Worker                 generated_item.attributes = EFI_MEMORY_ATTRIBUTE_EMA_RUNTIME;
189*5225e6b1SAndroid Build Coastguard Worker                 generated_item.memory_type = emat_item.memory_type;
190*5225e6b1SAndroid Build Coastguard Worker 
191*5225e6b1SAndroid Build Coastguard Worker                 // Adjust base and size forward.
192*5225e6b1SAndroid Build Coastguard Worker                 size -= emat_item.physical_start - base;
193*5225e6b1SAndroid Build Coastguard Worker                 base = emat_item.physical_start;
194*5225e6b1SAndroid Build Coastguard Worker             } else {
195*5225e6b1SAndroid Build Coastguard Worker                 // emat_item.physical_start == base
196*5225e6b1SAndroid Build Coastguard Worker                 // Create a region for [base ... emat_item->NumberOfPages * PAGE_SIZE)
197*5225e6b1SAndroid Build Coastguard Worker                 let mut generated_item;
198*5225e6b1SAndroid Build Coastguard Worker                 (generated_item, tail) = Ref::<_, EfiMemoryDescriptor>::new_from_prefix(tail)
199*5225e6b1SAndroid Build Coastguard Worker                     .ok_or(UnificationError(BufferTooSmall(Some(
200*5225e6b1SAndroid Build Coastguard Worker                         size_of::<EfiMemoryDescriptor>(),
201*5225e6b1SAndroid Build Coastguard Worker                     ))))?;
202*5225e6b1SAndroid Build Coastguard Worker                 *generated_item = *emat_item;
203*5225e6b1SAndroid Build Coastguard Worker 
204*5225e6b1SAndroid Build Coastguard Worker                 // Adjust base and size forward.
205*5225e6b1SAndroid Build Coastguard Worker                 base += emat_item.number_of_pages * PAGE_SIZE;
206*5225e6b1SAndroid Build Coastguard Worker                 size -= emat_item.number_of_pages * PAGE_SIZE;
207*5225e6b1SAndroid Build Coastguard Worker             }
208*5225e6b1SAndroid Build Coastguard Worker         }
209*5225e6b1SAndroid Build Coastguard Worker 
210*5225e6b1SAndroid Build Coastguard Worker         if size != 0 {
211*5225e6b1SAndroid Build Coastguard Worker             let mut generated_item;
212*5225e6b1SAndroid Build Coastguard Worker             (generated_item, tail) = Ref::<_, EfiMemoryDescriptor>::new_from_prefix(tail)
213*5225e6b1SAndroid Build Coastguard Worker                 .ok_or(UnificationError(BufferTooSmall(Some(size_of::<EfiMemoryDescriptor>()))))?;
214*5225e6b1SAndroid Build Coastguard Worker 
215*5225e6b1SAndroid Build Coastguard Worker             generated_item.physical_start = base;
216*5225e6b1SAndroid Build Coastguard Worker             generated_item.number_of_pages = size / PAGE_SIZE;
217*5225e6b1SAndroid Build Coastguard Worker             generated_item.virtual_start = 0;
218*5225e6b1SAndroid Build Coastguard Worker             generated_item.attributes = EFI_MEMORY_ATTRIBUTE_EMA_RUNTIME;
219*5225e6b1SAndroid Build Coastguard Worker             generated_item.memory_type = efi_memory_desc.memory_type;
220*5225e6b1SAndroid Build Coastguard Worker         }
221*5225e6b1SAndroid Build Coastguard Worker     }
222*5225e6b1SAndroid Build Coastguard Worker 
223*5225e6b1SAndroid Build Coastguard Worker     let used_payload = provided_payload_size - tail.len();
224*5225e6b1SAndroid Build Coastguard Worker     header.descriptor_size = size_of::<EfiMemoryDescriptor>().try_into().map_err(Error::from)?;
225*5225e6b1SAndroid Build Coastguard Worker     header.number_of_entries =
226*5225e6b1SAndroid Build Coastguard Worker         (used_payload / size_of::<EfiMemoryDescriptor>()).try_into().unwrap();
227*5225e6b1SAndroid Build Coastguard Worker     header.reserved = 0;
228*5225e6b1SAndroid Build Coastguard Worker     header.version = 1;
229*5225e6b1SAndroid Build Coastguard Worker 
230*5225e6b1SAndroid Build Coastguard Worker     zbi_items.create_entry(
231*5225e6b1SAndroid Build Coastguard Worker         ZbiType::EfiMemoryAttributesTable,
232*5225e6b1SAndroid Build Coastguard Worker         0,
233*5225e6b1SAndroid Build Coastguard Worker         ZbiFlags::default(),
234*5225e6b1SAndroid Build Coastguard Worker         used_payload,
235*5225e6b1SAndroid Build Coastguard Worker     )?;
236*5225e6b1SAndroid Build Coastguard Worker 
237*5225e6b1SAndroid Build Coastguard Worker     Ok(())
238*5225e6b1SAndroid Build Coastguard Worker }
239*5225e6b1SAndroid Build Coastguard Worker 
generate_mem_config_item<'b, B>( efi_memory_map: &EfiMemoryMap<'b>, zbi_items: &mut ZbiContainer<B>, ) -> Result<()> where B: ByteSliceMut + PartialEq,240*5225e6b1SAndroid Build Coastguard Worker fn generate_mem_config_item<'b, B>(
241*5225e6b1SAndroid Build Coastguard Worker     efi_memory_map: &EfiMemoryMap<'b>,
242*5225e6b1SAndroid Build Coastguard Worker     zbi_items: &mut ZbiContainer<B>,
243*5225e6b1SAndroid Build Coastguard Worker ) -> Result<()>
244*5225e6b1SAndroid Build Coastguard Worker where
245*5225e6b1SAndroid Build Coastguard Worker     B: ByteSliceMut + PartialEq,
246*5225e6b1SAndroid Build Coastguard Worker {
247*5225e6b1SAndroid Build Coastguard Worker     let mut tail = zbi_items.get_next_payload()?;
248*5225e6b1SAndroid Build Coastguard Worker     let provided_payload_size = tail.len();
249*5225e6b1SAndroid Build Coastguard Worker 
250*5225e6b1SAndroid Build Coastguard Worker     for efi_desc in efi_memory_map.into_iter() {
251*5225e6b1SAndroid Build Coastguard Worker         let mut zbi_mem_range: Ref<&mut [u8], zbi_mem_range_t>;
252*5225e6b1SAndroid Build Coastguard Worker         (zbi_mem_range, tail) = Ref::new_from_prefix(tail)
253*5225e6b1SAndroid Build Coastguard Worker             .ok_or(UnificationError(BufferTooSmall(Some(size_of::<zbi_mem_range_t>()))))?;
254*5225e6b1SAndroid Build Coastguard Worker         zbi_mem_range.paddr = efi_desc.physical_start;
255*5225e6b1SAndroid Build Coastguard Worker         zbi_mem_range.length = efi_desc.number_of_pages * PAGE_SIZE;
256*5225e6b1SAndroid Build Coastguard Worker         zbi_mem_range.type_ = efi_to_zbi_mem_range_type(efi_desc.memory_type);
257*5225e6b1SAndroid Build Coastguard Worker         zbi_mem_range.reserved = 0;
258*5225e6b1SAndroid Build Coastguard Worker     }
259*5225e6b1SAndroid Build Coastguard Worker 
260*5225e6b1SAndroid Build Coastguard Worker     let used_payload = provided_payload_size - tail.len();
261*5225e6b1SAndroid Build Coastguard Worker     zbi_items.create_entry(ZbiType::MemConfig, 0, ZbiFlags::default(), used_payload)?;
262*5225e6b1SAndroid Build Coastguard Worker 
263*5225e6b1SAndroid Build Coastguard Worker     Ok(())
264*5225e6b1SAndroid Build Coastguard Worker }
265