Changeset 100009 in vbox for trunk/src/VBox/Runtime/common/misc
- Timestamp:
- May 30, 2023 9:55:31 AM (23 months ago)
- svn:sync-xref-src-repo-rev:
- 157677
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/fdt.cpp
r100007 r100009 68 68 { 69 69 /** Pointer to the string block. */ 70 const char *paszStrings; 70 char *paszStrings; 71 /** Pointer to the raw structs block. */ 72 uint32_t *pu32Structs; 73 /** Pointer to the array of memory reservation entries. */ 74 PDTBFDTRSVENTRY paMemRsv; 75 /** Number of memory reservation entries. */ 76 uint32_t cMemRsv; 77 /** The DTB header (converted to host endianess). */ 78 DTBFDTHDR DtbHdr; 71 79 } RTFDTINT; 72 80 /** Pointer to the internal Flattened Devicetree instance. */ … … 118 126 * @param pErrInfo Where to return additional error information. 119 127 */ 120 static int rtFdtDtbHdr_Validate(PCDTBFDTHDR pDtbHdr, uint64_t cbDtb, PRTERRINFO pErrInfo) 121 { 122 RT_NOREF(pDtbHdr, cbDtb, pErrInfo); 128 static int rtFdtDtbHdr_Validate(PDTBFDTHDR pDtbHdr, uint64_t cbDtb, PRTERRINFO pErrInfo) 129 { 130 /* Convert to host endianess first. */ 131 pDtbHdr->u32Magic = RT_BE2H_U32(pDtbHdr->u32Magic); 132 pDtbHdr->cbFdt = RT_BE2H_U32(pDtbHdr->cbFdt); 133 pDtbHdr->offDtStruct = RT_BE2H_U32(pDtbHdr->offDtStruct); 134 pDtbHdr->offDtStrings = RT_BE2H_U32(pDtbHdr->offDtStrings); 135 pDtbHdr->offMemRsvMap = RT_BE2H_U32(pDtbHdr->offMemRsvMap); 136 pDtbHdr->u32Version = RT_BE2H_U32(pDtbHdr->u32Version); 137 pDtbHdr->u32VersionLastCompatible = RT_BE2H_U32(pDtbHdr->u32VersionLastCompatible); 138 pDtbHdr->u32CpuIdPhysBoot = RT_BE2H_U32(pDtbHdr->u32CpuIdPhysBoot); 139 pDtbHdr->cbDtStrings = RT_BE2H_U32(pDtbHdr->cbDtStrings); 140 pDtbHdr->cbDtStruct = RT_BE2H_U32(pDtbHdr->cbDtStruct); 141 142 if (pDtbHdr->u32Magic != DTBFDTHDR_MAGIC) 143 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_HDR_MAGIC_INVALID, "The magic of the DTB header is invalid (expected %#RX32, got %#RX32)", 144 DTBFDTHDR_MAGIC, pDtbHdr->u32Magic); 145 if (pDtbHdr->u32Version != DTBFDTHDR_VERSION) 146 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_HDR_VERSION_NOT_SUPPORTED, "Version %u of the DTB is not supported (supported is %u)", 147 pDtbHdr->u32Version, DTBFDTHDR_VERSION); 148 if (pDtbHdr->u32VersionLastCompatible != DTBFDTHDR_VERSION_LAST_COMP) 149 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_HDR_LAST_COMPAT_VERSION_INVALID, "Last compatible version %u of the DTB is invalid (expected %u)", 150 pDtbHdr->u32VersionLastCompatible, DTBFDTHDR_VERSION_LAST_COMP); 151 if (pDtbHdr->cbFdt != cbDtb) 152 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_HDR_SIZE_INVALID, "The size of the FDT is invalid (expected %RU32, got %RU32)", 153 cbDtb, pDtbHdr->cbFdt); 154 155 /* 156 * Check that any of the offsets is inside the bounds of the FDT and that the memory reservation block comes first, 157 * then the structs block and strings last. 158 */ 159 if ( pDtbHdr->offMemRsvMap >= pDtbHdr->cbFdt 160 || pDtbHdr->offMemRsvMap < sizeof(*pDtbHdr)) 161 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_HDR_MEM_RSV_BLOCK_OFF_INVALID, "Memory reservation block offset is out of bounds (offMemRsvMap=%#RX32 vs. cbFdt=%#%RX32)", 162 pDtbHdr->offMemRsvMap, pDtbHdr->cbFdt); 163 if ( pDtbHdr->offDtStruct >= pDtbHdr->cbFdt 164 || (pDtbHdr->cbFdt - pDtbHdr->offDtStruct < pDtbHdr->cbDtStruct) 165 || pDtbHdr->offDtStruct <= pDtbHdr->offMemRsvMap + sizeof(DTBFDTRSVENTRY)) 166 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_HDR_STRUCT_BLOCK_OFF_INVALID, "Structs block offset/size is out of bounds (offDtStruct=%#RX32 cbDtStruct=%#RX32 vs. cbFdt=%#RX32 offMemRsvMap=%#RX32)", 167 pDtbHdr->offDtStruct, pDtbHdr->cbDtStruct, pDtbHdr->cbFdt, pDtbHdr->offMemRsvMap); 168 if ( pDtbHdr->offDtStrings >= pDtbHdr->cbFdt 169 || (pDtbHdr->cbFdt - pDtbHdr->offDtStrings < pDtbHdr->cbDtStrings) 170 || pDtbHdr->offDtStrings < pDtbHdr->offDtStruct + pDtbHdr->cbDtStruct) 171 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_HDR_STRINGS_BLOCK_OFF_INVALID, "Strings block offset/size is out of bounds (offDtStrings=%#RX32 cbDtStrings=%#RX32 vs. cbFdt=%#%RX32 offDtStruct=%#RX32)", 172 pDtbHdr->offDtStrings, pDtbHdr->cbDtStrings, pDtbHdr->cbFdt, pDtbHdr->offDtStruct); 173 174 return VINF_SUCCESS; 175 } 176 177 178 /** 179 * Fres all resources allocated for the given FDT. 180 * 181 * @param pThis The FDT instance to destroy. 182 */ 183 static void rtFdtDestroy(PRTFDTINT pThis) 184 { 185 if (pThis->paszStrings) 186 RTMemFree(pThis->paszStrings); 187 if (pThis->pu32Structs) 188 RTMemFree(pThis->pu32Structs); 189 if (pThis->paMemRsv) 190 RTMemFree(pThis->paMemRsv); 191 192 pThis->paszStrings = NULL; 193 pThis->pu32Structs = NULL; 194 pThis->paMemRsv = NULL; 195 pThis->cMemRsv = 0; 196 RT_ZERO(pThis->DtbHdr); 197 RTMemFree(pThis); 198 } 199 200 201 /** 202 * Loads the memory reservation block from the underlying VFS I/O stream. 203 * 204 * @returns IPRT status code. 205 * @param pThis The FDT instance. 206 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 207 * @param pErrInfo Where to return additional error information. 208 */ 209 static int rtFdtDtbMemRsvLoad(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 210 { 211 AssertReturn(pThis->DtbHdr.offMemRsvMap < pThis->DtbHdr.offDtStruct, VERR_INTERNAL_ERROR); 212 213 uint32_t cMemRsvMax = (pThis->DtbHdr.offDtStruct - pThis->DtbHdr.offMemRsvMap) / sizeof(*pThis->paMemRsv); 214 Assert(cMemRsvMax); 215 216 pThis->paMemRsv = (PDTBFDTRSVENTRY)RTMemAllocZ(cMemRsvMax * sizeof(*pThis->paMemRsv)); 217 if (!pThis->paMemRsv) 218 return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %u bytes of memory for the memory reservation block", 219 cMemRsvMax * sizeof(*pThis->paMemRsv)); 220 221 /* Read the entries one after another until the terminator is reached. */ 222 uint32_t cMemRsv = 0; 223 for (;;) 224 { 225 DTBFDTRSVENTRY MemRsv; 226 int rc = RTVfsIoStrmRead(hVfsIos, &MemRsv, sizeof(MemRsv), true /*fBlocking*/, NULL /*pcbRead*/); 227 if (RT_FAILURE(rc)) 228 return RTErrInfoSetF(pErrInfo, rc, "Failed to read memory reservation entry %u from I/O stream", 229 cMemRsv); 230 231 /* Check whether the terminator is reached (no need to convert endianness here). */ 232 if ( MemRsv.PhysAddrStart == 0 233 && MemRsv.cbArea == 0) 234 break; 235 236 /* 237 * The terminator must be included in the maximum entry count, if not 238 * the DTB is malformed and lacks a terminating entry before the start of the structs block. 239 */ 240 if (cMemRsv + 1 == cMemRsvMax) 241 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_MEM_RSV_BLOCK_TERMINATOR_MISSING, 242 "The memory reservation block lacks a terminating entry"); 243 244 pThis->paMemRsv[cMemRsv].PhysAddrStart = RT_BE2H_U64(MemRsv.PhysAddrStart); 245 pThis->paMemRsv[cMemRsv].cbArea = RT_BE2H_U64(MemRsv.cbArea); 246 cMemRsv++; 247 } 248 249 pThis->cMemRsv = cMemRsv + 1; 250 return VINF_SUCCESS; 251 } 252 253 254 /** 255 * Loads the structs block of the given FDT. 256 * 257 * @returns IPRT status code. 258 * @param pThis The FDT instance. 259 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 260 * @param pErrInfo Where to return additional error information. 261 */ 262 static int rtFdtDtbStructsLoad(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 263 { 264 pThis->pu32Structs = (uint32_t *)RTMemAllocZ(pThis->DtbHdr.cbDtStruct); 265 if (!pThis->pu32Structs) 266 return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %u bytes of memory for the structs block", 267 pThis->DtbHdr.cbDtStruct); 268 269 int rc = RTVfsIoStrmRead(hVfsIos, pThis->pu32Structs, pThis->DtbHdr.cbDtStruct, true /*fBlocking*/, NULL /*pcbRead*/); 270 if (RT_FAILURE(rc)) 271 return RTErrInfoSetF(pErrInfo, rc, "Failed to read structs block from I/O stream"); 272 273 return VINF_SUCCESS; 274 } 275 276 277 /** 278 * Loads the strings block of the given FDT. 279 * 280 * @returns IPRT status code. 281 * @param pThis The FDT instance. 282 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 283 * @param pErrInfo Where to return additional error information. 284 */ 285 static int rtFdtDtbStringsLoad(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 286 { 287 pThis->paszStrings = (char *)RTMemAllocZ(pThis->DtbHdr.cbDtStrings); 288 if (!pThis->paszStrings) 289 return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %u bytes of memory for the strings block", 290 pThis->DtbHdr.cbDtStrings); 291 292 int rc = RTVfsIoStrmRead(hVfsIos, pThis->paszStrings, pThis->DtbHdr.cbDtStrings, true /*fBlocking*/, NULL /*pcbRead*/); 293 if (RT_FAILURE(rc)) 294 return RTErrInfoSetF(pErrInfo, rc, "Failed to read strings block from I/O stream"); 295 296 /* Verify that the strings block is terminated. */ 297 if (pThis->paszStrings[pThis->DtbHdr.cbDtStrings - 1] != '\0') 298 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRINGS_BLOCK_NOT_TERMINATED, "The strings block is not zero temrinated"); 299 123 300 return VINF_SUCCESS; 124 301 } … … 153 330 if (RT_SUCCESS(rc)) 154 331 { 155 RT_NOREF(phFdt); 332 PRTFDTINT pThis = (PRTFDTINT)RTMemAllocZ(sizeof(*pThis)); 333 if (RT_LIKELY(pThis)) 334 { 335 memcpy(&pThis->DtbHdr, &DtbHdr, sizeof(DtbHdr)); 336 337 /* Load the memory reservation block. */ 338 rc = rtFdtDtbMemRsvLoad(pThis, hVfsIos, pErrInfo); 339 if (RT_SUCCESS(rc)) 340 { 341 rc = rtFdtDtbStructsLoad(pThis, hVfsIos, pErrInfo); 342 if (RT_SUCCESS(rc)) 343 { 344 rc = rtFdtDtbStringsLoad(pThis, hVfsIos, pErrInfo); 345 if (RT_SUCCESS(rc)) 346 { 347 *phFdt = pThis; 348 return VINF_SUCCESS; 349 } 350 } 351 } 352 353 rtFdtDestroy(pThis); 354 } 355 else 356 RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Failed to allocate memory for the FDT"); 156 357 } 157 358 } 158 359 else 159 RTErrInfoSetF(pErrInfo, rc, "Failed to read %u bytes for the DTB header -> %Rrc \n",160 sizeof(DtbHdr) );360 RTErrInfoSetF(pErrInfo, rc, "Failed to read %u bytes for the DTB header -> %Rrc", 361 sizeof(DtbHdr), rc); 161 362 } 162 363 else 163 RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_MALFORMED, "DTB is too small, needs at least %u bytes, only %u available \n",364 RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_MALFORMED, "DTB is too small, needs at least %u bytes, only %u available", 164 365 sizeof(DtbHdr) + sizeof(DTBFDTRSVENTRY), ObjInfo.cbObject); 165 366 } 166 367 else 167 RTErrInfoSetF(pErrInfo, rc, "Failed to query size of the DTB -> %Rrc \n", rc);368 RTErrInfoSetF(pErrInfo, rc, "Failed to query size of the DTB -> %Rrc", rc); 168 369 169 370 return rc; … … 199 400 RTDECL(void) RTFdtDestroy(RTFDT hFdt) 200 401 { 201 RT_NOREF(hFdt); 402 PRTFDTINT pThis = hFdt; 403 AssertPtrReturnVoid(pThis); 404 405 rtFdtDestroy(pThis); 202 406 } 203 407
Note:
See TracChangeset
for help on using the changeset viewer.