Reads the layout of physical memory from the flattened device tree (FDT), splitting it (logically) into confidential and non-confidential memory region. The FDT content is trusted. # Guarantees The end of the confidential memory is not lower than the start of the confidential memory
(fdt: &FlattenedDeviceTree)
| 116 | /// |
| 117 | /// The end of the confidential memory is not lower than the start of the confidential memory |
| 118 | fn initialize_memory_layout(fdt: &FlattenedDeviceTree) -> Result<(ConfidentialMemoryAddress, *const usize), Error> { |
| 119 | // TODO: FDT may contain multiple regions. For now, we assume there is only one region in the FDT. |
| 120 | // This assumption is fine for the emulated environment (QEMU). |
| 121 | |
| 122 | // Information read from FDT is trusted assuming we are executing as part of a measured and secure boot. So we trust that we read the |
| 123 | // correct base and size of the memory. |
| 124 | let fdt_memory_region = fdt.memory()?; |
| 125 | // Safety: We own all the memory because we are early in the boot process and have full rights to split memory according to our needs. |
| 126 | // Thus, it is fine to cast `usize` to `*mut usize`. |
| 127 | let memory_start = fdt_memory_region.base as *mut usize; |
| 128 | // In assembly that executed this initialization function splitted the memory into two regions where |
| 129 | // the second region's size is equal or greater than the first ones. |
| 130 | let non_confidential_memory_size = fdt_memory_region.size.try_into().map_err(|_| Error::InvalidMemoryBoundary())?; |
| 131 | let confidential_memory_size = non_confidential_memory_size; |
| 132 | let memory_size = non_confidential_memory_size + confidential_memory_size; |
| 133 | let memory_end = memory_start.wrapping_byte_add(memory_size) as *const usize; |
| 134 | debug!("Memory 0x{:#?}-0x{:#?}", memory_start, memory_end); |
| 135 | |
| 136 | // First region of memory is defined as non-confidential memory |
| 137 | let non_confidential_memory_start = memory_start; |
| 138 | let non_confidential_memory_end = ptr_byte_add_mut(non_confidential_memory_start, non_confidential_memory_size, memory_end) |
| 139 | .map_err(|_| Error::InvalidMemoryBoundary())?; |
| 140 | debug!("Non-confidential memory 0x{:#?}-0x{:#?}", non_confidential_memory_start, non_confidential_memory_end); |
| 141 | |
| 142 | // Second region of memory is defined as confidential memory |
| 143 | let confidential_memory_start = non_confidential_memory_end; |
| 144 | let confidential_memory_end = memory_end; |
| 145 | debug!("Confidential memory 0x{:#?}-0x{:#?}", confidential_memory_start, confidential_memory_end); |
| 146 | |
| 147 | unsafe { |
| 148 | MemoryLayout::init(non_confidential_memory_start, non_confidential_memory_end, confidential_memory_start, confidential_memory_end) |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | /// This function is called only once during the initialization of the security |
| 153 | /// monitor during the boot process. This function initializes secure monitor's |
no test coverage detected