Changeset 100029 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Jun 1, 2023 11:06:25 AM (20 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/fdt.cpp
r100024 r100029 47 47 #include <iprt/log.h> 48 48 #include <iprt/mem.h> 49 #include <iprt/s trcache.h>49 #include <iprt/sg.h> 50 50 #include <iprt/string.h> 51 51 #include <iprt/vfs.h> 52 #include <iprt/zero.h> 52 53 #include <iprt/formats/dtb.h> 53 54 … … 73 74 char *paszStrings; 74 75 /** Pointer to the raw structs block. */ 75 uint 32_t *pu32Structs;76 uint8_t *pbStruct; 76 77 /** Pointer to the array of memory reservation entries. */ 77 78 PDTBFDTRSVENTRY paMemRsv; 78 79 /** Number of memory reservation entries. */ 79 80 uint32_t cMemRsv; 80 /** The DTB header (converted to host endianess). */ 81 DTBFDTHDR DtbHdr; 81 /** Maximum number of memory reservation entries allocated. */ 82 uint32_t cMemRsvMax; 83 /** Size of the strings block. */ 84 uint32_t cbStrings; 85 /** Allocated size of the string block. */ 86 uint32_t cbStringsMax; 87 /** Size of the struct block. */ 88 uint32_t cbStruct; 89 /** Allocated size of the struct block. */ 90 uint32_t cbStructMax; 91 /** The physical boot CPU ID. */ 92 uint32_t u32CpuIdPhysBoot; 93 /** Current tree depth in the structure block. */ 94 uint32_t cTreeDepth; 82 95 } RTFDTINT; 83 96 /** Pointer to the internal Flattened Devicetree instance. */ … … 237 250 if (pThis->paszStrings) 238 251 RTMemFree(pThis->paszStrings); 239 if (pThis->p u32Structs)240 RTMemFree(pThis->p u32Structs);252 if (pThis->pbStruct) 253 RTMemFree(pThis->pbStruct); 241 254 if (pThis->paMemRsv) 242 255 RTMemFree(pThis->paMemRsv); 243 256 244 pThis->paszStrings = NULL; 245 pThis->pu32Structs = NULL; 246 pThis->paMemRsv = NULL; 247 pThis->cMemRsv = 0; 248 RT_ZERO(pThis->DtbHdr); 257 pThis->paszStrings = NULL; 258 pThis->pbStruct = NULL; 259 pThis->paMemRsv = NULL; 260 pThis->cMemRsv = 0; 261 pThis->cMemRsvMax = 0; 262 pThis->cbStrings = 0; 263 pThis->cbStringsMax = 0; 264 pThis->cbStruct = 0; 265 pThis->cbStructMax = 0; 266 pThis->u32CpuIdPhysBoot = 0; 267 pThis->cTreeDepth = 0; 249 268 RTMemFree(pThis); 250 269 } … … 256 275 * @returns IPRT status code. 257 276 * @param pThis Pointer to the FDT instance. 277 * @param pDtbHdr The DTB header. 258 278 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 259 279 * @param pErrInfo Where to return additional error information. 260 280 */ 261 static int rtFdtDtbMemRsvLoad(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo)262 { 263 AssertReturn(p This->DtbHdr.offMemRsvMap < pThis->DtbHdr.offDtStruct, VERR_INTERNAL_ERROR);264 265 uint32_t cMemRsvMax = (p This->DtbHdr.offDtStruct - pThis->DtbHdr.offMemRsvMap) / sizeof(*pThis->paMemRsv);281 static int rtFdtDtbMemRsvLoad(PRTFDTINT pThis, PCDTBFDTHDR pDtbHdr, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 282 { 283 AssertReturn(pDtbHdr->offMemRsvMap < pDtbHdr->offDtStruct, VERR_INTERNAL_ERROR); 284 285 uint32_t cMemRsvMax = (pDtbHdr->offDtStruct - pDtbHdr->offMemRsvMap) / sizeof(*pThis->paMemRsv); 266 286 Assert(cMemRsvMax); 267 287 … … 270 290 return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %u bytes of memory for the memory reservation block", 271 291 cMemRsvMax * sizeof(*pThis->paMemRsv)); 292 293 pThis->cMemRsvMax = cMemRsvMax; 272 294 273 295 /* Read the entries one after another until the terminator is reached. */ … … 310 332 * @returns IPRT status code. 311 333 * @param pThis Pointer to the FDT instance. 334 * @param pDtbHdr The DTB header. 312 335 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 313 336 * @param pErrInfo Where to return additional error information. 314 337 */ 315 static int rtFdtDtbStructsLoad(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo)316 { 317 pThis->p u32Structs = (uint32_t *)RTMemAllocZ(pThis->DtbHdr.cbDtStruct);318 if (!pThis->p u32Structs)338 static int rtFdtDtbStructsLoad(PRTFDTINT pThis, PCDTBFDTHDR pDtbHdr, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 339 { 340 pThis->pbStruct = (uint8_t *)RTMemAllocZ(pDtbHdr->cbDtStruct); 341 if (!pThis->pbStruct) 319 342 return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %u bytes of memory for the structs block", 320 p This->DtbHdr.cbDtStruct);321 322 int rc = RTVfsIoStrmReadAt(hVfsIos, p This->DtbHdr.offDtStruct, pThis->pu32Structs, pThis->DtbHdr.cbDtStruct,343 pDtbHdr->cbDtStruct); 344 345 int rc = RTVfsIoStrmReadAt(hVfsIos, pDtbHdr->offDtStruct, pThis->pbStruct, pDtbHdr->cbDtStruct, 323 346 true /*fBlocking*/, NULL /*pcbRead*/); 324 347 if (RT_FAILURE(rc)) … … 334 357 * @returns IPRT status code. 335 358 * @param pThis Pointer to the FDT instance. 359 * @param pDtbHdr The DTB header. 336 360 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 337 361 * @param pErrInfo Where to return additional error information. 338 362 */ 339 static int rtFdtDtbStringsLoad(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo)340 { 341 pThis->paszStrings = (char *)RTMemAllocZ(p This->DtbHdr.cbDtStrings);363 static int rtFdtDtbStringsLoad(PRTFDTINT pThis, PCDTBFDTHDR pDtbHdr, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 364 { 365 pThis->paszStrings = (char *)RTMemAllocZ(pDtbHdr->cbDtStrings); 342 366 if (!pThis->paszStrings) 343 367 return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %u bytes of memory for the strings block", 344 p This->DtbHdr.cbDtStrings);345 346 int rc = RTVfsIoStrmReadAt(hVfsIos, p This->DtbHdr.offDtStrings, pThis->paszStrings, pThis->DtbHdr.cbDtStrings,368 pDtbHdr->cbDtStrings); 369 370 int rc = RTVfsIoStrmReadAt(hVfsIos, pDtbHdr->offDtStrings, pThis->paszStrings, pDtbHdr->cbDtStrings, 347 371 true /*fBlocking*/, NULL /*pcbRead*/); 348 372 if (RT_FAILURE(rc)) … … 350 374 351 375 /* Verify that the strings block is terminated. */ 352 if (pThis->paszStrings[p This->DtbHdr.cbDtStrings - 1] != '\0')376 if (pThis->paszStrings[pDtbHdr->cbDtStrings - 1] != '\0') 353 377 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRINGS_BLOCK_NOT_TERMINATED, "The strings block is not zero terminated"); 354 378 … … 388 412 if (RT_LIKELY(pThis)) 389 413 { 390 memcpy(&pThis->DtbHdr, &DtbHdr, sizeof(DtbHdr)); 414 pThis->cbStrings = DtbHdr.cbDtStrings; 415 pThis->cbStruct = DtbHdr.cbDtStruct; 416 pThis->u32CpuIdPhysBoot = DtbHdr.u32CpuIdPhysBoot; 391 417 392 418 /* Load the memory reservation block. */ 393 rc = rtFdtDtbMemRsvLoad(pThis, hVfsIos, pErrInfo);419 rc = rtFdtDtbMemRsvLoad(pThis, &DtbHdr, hVfsIos, pErrInfo); 394 420 if (RT_SUCCESS(rc)) 395 421 { 396 rc = rtFdtDtbStructsLoad(pThis, hVfsIos, pErrInfo);422 rc = rtFdtDtbStructsLoad(pThis, &DtbHdr, hVfsIos, pErrInfo); 397 423 if (RT_SUCCESS(rc)) 398 424 { 399 rc = rtFdtDtbStringsLoad(pThis, hVfsIos, pErrInfo);425 rc = rtFdtDtbStringsLoad(pThis, &DtbHdr, hVfsIos, pErrInfo); 400 426 if (RT_SUCCESS(rc)) 401 427 { 428 pThis->cbStringsMax = pThis->cbStrings; 429 pThis->cbStructMax = pThis->cbStruct; 430 402 431 *phFdt = pThis; 403 432 return VINF_SUCCESS; … … 456 485 DECLINLINE(size_t) rtFdtStructsGetOffset(PRTFDTINT pThis, PCRTFDTDTBDUMP pDump) 457 486 { 458 return pThis-> DtbHdr.cbDtStruct - pDump->cbLeft - sizeof(uint32_t);487 return pThis->cbStruct - pDump->cbLeft - sizeof(uint32_t); 459 488 } 460 489 #endif … … 728 757 Prop.cbProperty = RT_BE2H_U32(Prop.cbProperty); 729 758 730 if (Prop.offPropertyName >= pThis-> DtbHdr.cbDtStrings)759 if (Prop.offPropertyName >= pThis->cbStrings) 731 760 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_PROP_NAME_OFF_TOO_LARGE, "Property name offset points past the string block"); 732 761 … … 845 874 RTFDTDTBDUMP Dump; 846 875 847 Dump.cbLeft = pThis-> DtbHdr.cbDtStruct;848 Dump.pbStructs = (const uint8_t *)pThis->pu32Structs;876 Dump.cbLeft = pThis->cbStruct; 877 Dump.pbStructs = pThis->pbStruct; 849 878 850 879 /* Skip any NOP tokens. */ … … 948 977 cch = RTVfsIoStrmPrintf(hVfsIos, "/memreserve/ %#RX64 %#RX64;\n", pThis->paMemRsv[i].PhysAddrStart, pThis->paMemRsv[i].cbArea); 949 978 if (cch <= 0) 950 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write memory re ervation block %u", i);979 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write memory reservation block %u", i); 951 980 } 952 981 … … 956 985 957 986 987 /** 988 * Adds the zero padding to align the next block properly. 989 * 990 * @returns IPRT status code. 991 * @param hVfsIos The VFS I/O stream handle to dump the DTB to. 992 * @param cbPad How many bytes to pad. 993 */ 994 static int rtFdtDumpAsDtbPad(RTVFSIOSTREAM hVfsIos, uint32_t cbPad) 995 { 996 if (!cbPad) 997 return VINF_SUCCESS; 998 999 while (cbPad) 1000 { 1001 uint32_t cbThisPad = RT_MIN(cbPad, _4K); 1002 int rc = RTVfsIoStrmWrite(hVfsIos, &g_abRTZero4K[0], cbThisPad, true /*fBlocking*/, NULL /*pcbWritten*/); 1003 if (RT_FAILURE(rc)) 1004 return rc; 1005 1006 cbPad -= cbThisPad; 1007 } 1008 1009 return VINF_SUCCESS; 1010 } 1011 1012 1013 /** 1014 * Dumps the given FDT instance as a DTB (Devicetree blob). 1015 * 1016 * @returns IPRT status code. 1017 * @param pThis Pointer to the FDT instance. 1018 * @param hVfsIos The VFS I/O stream handle to dump the DTB to. 1019 * @param pErrInfo Where to return additional error information. 1020 */ 1021 static int rtFdtDumpAsDtb(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 1022 { 1023 DTBFDTHDR Hdr; 1024 1025 /* ensure the FDT is finalized. */ 1026 int rc = RTFdtFinalize(pThis); 1027 if (RT_FAILURE(rc)) 1028 return rc; 1029 1030 uint32_t offMemRsvMap = RT_ALIGN_32(sizeof(Hdr), sizeof(uint64_t)); 1031 uint32_t offDtStruct = RT_ALIGN_32(offMemRsvMap + (pThis->cMemRsv + 1) * sizeof(DTBFDTRSVENTRY), sizeof(uint32_t)); 1032 uint32_t offDtStrings = offDtStruct + pThis->cbStruct; 1033 uint32_t cbFdt = offDtStrings + pThis->cbStrings; 1034 uint32_t cbCur = 0; 1035 1036 Hdr.u32Magic = RT_H2BE_U32(DTBFDTHDR_MAGIC); 1037 Hdr.cbFdt = RT_H2BE_U32(cbFdt); 1038 Hdr.offDtStruct = RT_H2BE_U32(offDtStruct); 1039 Hdr.offDtStrings = RT_H2BE_U32(offDtStrings); 1040 Hdr.offMemRsvMap = RT_H2BE_U32(offMemRsvMap); 1041 Hdr.u32Version = RT_H2BE_U32(DTBFDTHDR_VERSION); 1042 Hdr.u32VersionLastCompatible = RT_H2BE_U32(DTBFDTHDR_VERSION_LAST_COMP); 1043 Hdr.u32CpuIdPhysBoot = RT_H2BE_U32(pThis->u32CpuIdPhysBoot); 1044 Hdr.cbDtStrings = RT_H2BE_U32(pThis->cbStrings); 1045 Hdr.cbDtStruct = RT_H2BE_U32(pThis->cbStruct); 1046 1047 /* Write out header, memory reservation block, struct block and strings block all with appropriate padding. */ 1048 rc = RTVfsIoStrmWrite(hVfsIos, &Hdr, sizeof(Hdr), true /*fBlocking*/, NULL /*pcbWritten*/); 1049 if (RT_FAILURE(rc)) 1050 return RTErrInfoSetF(pErrInfo, rc, "Failed to write DTB header (%u bytes) to I/O stream", sizeof(Hdr)); 1051 1052 cbCur += sizeof(Hdr); 1053 rc = rtFdtDumpAsDtbPad(hVfsIos, offMemRsvMap - cbCur); 1054 if (RT_FAILURE(rc)) 1055 return RTErrInfoSetF(pErrInfo, rc, "Failed to write padding after DTB header (%u bytes) to I/O stream", 1056 offMemRsvMap - cbCur); 1057 cbCur += offMemRsvMap - cbCur; 1058 1059 /* Write memory reservation blocks. */ 1060 for (uint32_t i = 0; i < pThis->cMemRsv; i++) 1061 { 1062 DTBFDTRSVENTRY MemRsv; 1063 1064 MemRsv.PhysAddrStart = RT_H2BE_U32(pThis->paMemRsv[i].PhysAddrStart); 1065 MemRsv.cbArea = RT_H2BE_U32(pThis->paMemRsv[i].cbArea); 1066 rc = RTVfsIoStrmWrite(hVfsIos, &MemRsv, sizeof(MemRsv), true /*fBlocking*/, NULL /*pcbWritten*/); 1067 if (RT_FAILURE(rc)) 1068 return RTErrInfoSetF(pErrInfo, rc, "Failed to write memory reservation entry %u (%u bytes) to I/O stream", 1069 i, sizeof(MemRsv)); 1070 cbCur += sizeof(MemRsv); 1071 } 1072 1073 /* Always write terminating entry. */ 1074 DTBFDTRSVENTRY RsvTerm; 1075 RsvTerm.PhysAddrStart = RT_H2BE_U32(0); /* Yeah, pretty useful endianess conversion I know */ 1076 RsvTerm.cbArea = RT_H2BE_U32(0); 1077 rc = RTVfsIoStrmWrite(hVfsIos, &RsvTerm, sizeof(RsvTerm), true /*fBlocking*/, NULL /*pcbWritten*/); 1078 if (RT_FAILURE(rc)) 1079 return RTErrInfoSetF(pErrInfo, rc, "Failed to write terminating memory reservation entry (%u bytes) to I/O stream", 1080 sizeof(RsvTerm)); 1081 cbCur += sizeof(RsvTerm); 1082 1083 rc = rtFdtDumpAsDtbPad(hVfsIos, offDtStruct - cbCur); 1084 if (RT_FAILURE(rc)) 1085 return RTErrInfoSetF(pErrInfo, rc, "Failed to write padding after memory reservation block (%u bytes) to I/O stream", 1086 offDtStruct - cbCur); 1087 cbCur += offDtStruct - cbCur; 1088 1089 /* Write struct block. */ 1090 rc = RTVfsIoStrmWrite(hVfsIos, pThis->pbStruct, pThis->cbStruct, true /*fBlocking*/, NULL /*pcbWritten*/); 1091 if (RT_FAILURE(rc)) 1092 return RTErrInfoSetF(pErrInfo, rc, "Failed to write struct block (%u bytes) to I/O stream", 1093 pThis->cbStruct); 1094 cbCur += pThis->cbStruct; 1095 1096 rc = rtFdtDumpAsDtbPad(hVfsIos, offDtStrings - cbCur); 1097 if (RT_FAILURE(rc)) 1098 return RTErrInfoSetF(pErrInfo, rc, "Failed to write padding after structs block (%u bytes) to I/O stream", 1099 offDtStrings - cbCur); 1100 cbCur += offDtStrings - cbCur; 1101 1102 /* Write strings block. */ 1103 rc = RTVfsIoStrmWrite(hVfsIos, pThis->paszStrings, pThis->cbStrings, true /*fBlocking*/, NULL /*pcbWritten*/); 1104 if (RT_FAILURE(rc)) 1105 return RTErrInfoSetF(pErrInfo, rc, "Failed to write strings block (%u bytes) to I/O stream", 1106 pThis->cbStrings); 1107 cbCur += pThis->cbStrings; 1108 1109 rc = rtFdtDumpAsDtbPad(hVfsIos, cbFdt - cbCur); 1110 if (RT_FAILURE(rc)) 1111 return RTErrInfoSetF(pErrInfo, rc, "Failed to write padding after strings block (%u bytes) to I/O stream", 1112 cbFdt - cbCur); 1113 cbCur += cbFdt - cbCur; 1114 1115 Assert(cbCur == cbFdt); 1116 return VINF_SUCCESS; 1117 } 1118 1119 1120 /** 1121 * Ensures there is enough space in the structure block, allocating more if required. 1122 * 1123 * @returns IPRT status code. 1124 * @param pThis Pointer to the FDT instance. 1125 * @param cch Number of characters required, including the zero terminator. 1126 */ 1127 static int rtFdtStringsEnsureSpace(PRTFDTINT pThis, uint32_t cch) 1128 { 1129 if (pThis->cbStringsMax - pThis->cbStrings >= cch) 1130 return VINF_SUCCESS; 1131 1132 size_t cbNew = RT_ALIGN_32(pThis->cbStrings + cch, 256); 1133 void *pvStringsNew = RTMemReallocZ(pThis->paszStrings, pThis->cbStringsMax, cbNew); 1134 if (!pvStringsNew) 1135 return VERR_NO_MEMORY; 1136 1137 Assert(cbNew - pThis->cbStrings >= cch); 1138 pThis->paszStrings = (char *)pvStringsNew; 1139 pThis->cbStringsMax = cbNew; 1140 return VINF_SUCCESS; 1141 } 1142 1143 1144 /** 1145 * Looks for the given string in the strings block appending it if not found, returning 1146 * the offset of the occurrence. 1147 * 1148 * @returns IPRT status code. 1149 * @param pThis Pointer to the FDT instance. 1150 * @param psz The string to insert. 1151 * @param poffStr Where to store the offset of the start of string from the beginning 1152 * of the strings block on success. 1153 */ 1154 static int rtFdtStringsInsertString(PRTFDTINT pThis, const char *psz, uint32_t *poffStr) 1155 { 1156 uint32_t off = 0; 1157 while (off < pThis->cbStrings) 1158 { 1159 if (!RTStrCmp(psz, &pThis->paszStrings[off])) 1160 { 1161 *poffStr = off; 1162 return VINF_SUCCESS; 1163 } 1164 1165 /** @todo Optimize? The strings block is not very large though so probably not worth the effort. */ 1166 off += strlen(&pThis->paszStrings[off]) + 1; 1167 } 1168 1169 /* Not found, need to insert. */ 1170 size_t cch = strlen(psz) + 1; 1171 int rc = rtFdtStringsEnsureSpace(pThis, cch); 1172 if (RT_FAILURE(rc)) 1173 return rc; 1174 1175 memcpy(&pThis->paszStrings[off], psz, cch); 1176 pThis->cbStrings += cch; 1177 *poffStr = off; 1178 return VINF_SUCCESS; 1179 } 1180 1181 1182 /** 1183 * Ensures there is enough space in the structure block, allocating more if required. 1184 * 1185 * @returns IPRT status code. 1186 * @param pThis Pointer to the FDT instance. 1187 * @param cbSpaceRequired Number of bytes required. 1188 */ 1189 static int rtFdtStructEnsureSpace(PRTFDTINT pThis, uint32_t cbSpaceRequired) 1190 { 1191 if (pThis->cbStructMax - pThis->cbStruct >= cbSpaceRequired) 1192 return VINF_SUCCESS; 1193 1194 size_t cbNew = RT_ALIGN_32(pThis->cbStruct + cbSpaceRequired, _1K); 1195 void *pvStructNew = RTMemReallocZ(pThis->pbStruct, pThis->cbStructMax, cbNew); 1196 if (!pvStructNew) 1197 return VERR_NO_MEMORY; 1198 1199 Assert(cbNew - pThis->cbStruct >= cbSpaceRequired); 1200 pThis->pbStruct = (uint8_t *)pvStructNew; 1201 pThis->cbStructMax = cbNew; 1202 return VINF_SUCCESS; 1203 } 1204 1205 1206 /** 1207 * Appends the given token and payload data to the structure block taking care of aligning the data. 1208 * 1209 * @returns IPRT status code. 1210 * @param pThis Pointer to the FDT instance. 1211 * @param pSgBuf The S/G buffer to append. 1212 * @param cbAppend How many bytes to append. 1213 */ 1214 static int rtFdtStructAppendSg(PRTFDTINT pThis, PRTSGBUF pSgBuf, uint32_t cbAppend) 1215 { 1216 uint32_t cbAppendAligned = RT_ALIGN_32(cbAppend, sizeof(uint32_t)); 1217 1218 /* Ensure enough space for the token and the payload + padding. */ 1219 int rc = rtFdtStructEnsureSpace(pThis, cbAppendAligned); 1220 if (RT_FAILURE(rc)) 1221 return rc; 1222 1223 size_t cbCopied = RTSgBufCopyToBuf(pSgBuf, pThis->pbStruct + pThis->cbStruct, cbAppend); 1224 AssertReturn(cbCopied == cbAppend, VERR_INTERNAL_ERROR); 1225 1226 pThis->cbStruct += cbAppendAligned; 1227 return VINF_SUCCESS; 1228 } 1229 1230 1231 /** 1232 * Appends a token and payload data. 1233 * 1234 * @returns IPRT status code. 1235 * @param pThis Pointer to the FDT instance. 1236 * @param u32Token The token to append. 1237 * @param pvPayload Pointer to the payload data to append. 1238 * @param cbPayload Size of the payload data in bytes. 1239 */ 1240 static int rtFdtStructAppendTokenAndPayload(PRTFDTINT pThis, uint32_t u32Token, const void *pvPayload, size_t cbPayload) 1241 { 1242 RTSGBUF SgBuf; 1243 RTSGSEG aSegs[2]; 1244 1245 aSegs[0].pvSeg = &u32Token; 1246 aSegs[0].cbSeg = sizeof(u32Token); 1247 aSegs[1].pvSeg = (void *)pvPayload; 1248 aSegs[1].cbSeg = cbPayload; 1249 RTSgBufInit(&SgBuf, &aSegs[0], RT_ELEMENTS(aSegs)); 1250 1251 return rtFdtStructAppendSg(pThis, &SgBuf, sizeof(u32Token) + cbPayload); 1252 } 1253 1254 1255 /** 1256 * Appends a property. 1257 * 1258 * @returns IPRT status code. 1259 * @param pThis Pointer to the FDT instance. 1260 * @param pszProperty Name of the property. 1261 * @param pvProperty Pointer to the property data. 1262 * @param cbProperty Size of the property data in bytes. 1263 */ 1264 static int rtFdtStructAppendProperty(PRTFDTINT pThis, const char *pszProperty, const void *pvProperty, uint32_t cbProperty) 1265 { 1266 /* Insert the property name into the strings block. */ 1267 uint32_t offStr; 1268 int rc = rtFdtStringsInsertString(pThis, pszProperty, &offStr); 1269 if (RT_FAILURE(rc)) 1270 return rc; 1271 1272 uint32_t u32Token = DTB_FDT_TOKEN_PROPERTY_BE; 1273 DTBFDTPROP Prop; 1274 1275 Prop.cbProperty = RT_H2BE_U32(cbProperty); 1276 Prop.offPropertyName = RT_H2BE_U32(offStr); 1277 1278 RTSGBUF SgBuf; 1279 RTSGSEG aSegs[3]; 1280 aSegs[0].pvSeg = &u32Token; 1281 aSegs[0].cbSeg = sizeof(u32Token); 1282 aSegs[1].pvSeg = &Prop; 1283 aSegs[1].cbSeg = sizeof(Prop); 1284 if (cbProperty) 1285 { 1286 aSegs[2].pvSeg = (void *)pvProperty; 1287 aSegs[2].cbSeg = cbProperty; 1288 } 1289 RTSgBufInit(&SgBuf, &aSegs[0], cbProperty ? RT_ELEMENTS(aSegs) : 2); 1290 1291 return rtFdtStructAppendSg(pThis, &SgBuf, sizeof(u32Token) + sizeof(Prop) + cbProperty); 1292 } 1293 1294 958 1295 RTDECL(int) RTFdtCreateEmpty(PRTFDT phFdt) 959 1296 { 960 RT_NOREF(phFdt); 961 return VERR_NOT_IMPLEMENTED; 1297 AssertPtrReturn(phFdt, VERR_INVALID_POINTER); 1298 1299 int rc = VINF_SUCCESS; 1300 PRTFDTINT pThis = (PRTFDTINT)RTMemAllocZ(sizeof(*pThis)); 1301 if (pThis) 1302 { 1303 /* Add the root node. */ 1304 rc = RTFdtNodeAdd(pThis, ""); 1305 if (RT_SUCCESS(rc)) 1306 { 1307 *phFdt = pThis; 1308 return VINF_SUCCESS; 1309 } 1310 1311 RTMemFree(pThis); 1312 } 1313 else 1314 rc = VERR_NO_MEMORY; 1315 1316 return rc; 962 1317 } 963 1318 … … 991 1346 992 1347 993 RTDECL(int) RTFdt DumpToVfsIoStrm(RTFDT hFdt, RTFDTTYPE enmOutType, uint32_t fFlags, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo)1348 RTDECL(int) RTFdtFinalize(RTFDT hFdt) 994 1349 { 995 1350 PRTFDTINT pThis = hFdt; 996 1351 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 997 1352 998 RT_NOREF(fFlags); 1353 /* Already finalized? */ 1354 if (!pThis->cTreeDepth) 1355 return VINF_SUCCESS; 1356 1357 uint32_t cbStructSpace = pThis->cTreeDepth * sizeof(uint32_t) + sizeof(uint32_t); /* One extra for the END token. */ 1358 int rc = rtFdtStructEnsureSpace(pThis, cbStructSpace); 1359 if (RT_FAILURE(rc)) 1360 return rc; 1361 1362 uint32_t *pu32 = (uint32_t *)pThis->pbStruct; 1363 while (pThis->cTreeDepth--) 1364 *pu32++ = DTB_FDT_TOKEN_END_NODE_BE; 1365 1366 *pu32 = DTB_FDT_TOKEN_END_BE; 1367 pThis->cbStruct += cbStructSpace; 1368 return VINF_SUCCESS; 1369 } 1370 1371 1372 RTDECL(int) RTFdtDumpToVfsIoStrm(RTFDT hFdt, RTFDTTYPE enmOutType, uint32_t fFlags, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 1373 { 1374 PRTFDTINT pThis = hFdt; 1375 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1376 AssertReturn(enmOutType == RTFDTTYPE_DTS || enmOutType == RTFDTTYPE_DTB, VERR_INVALID_PARAMETER); 1377 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); 1378 999 1379 if (enmOutType == RTFDTTYPE_DTS) 1000 1380 return rtFdtDumpAsDts(pThis, hVfsIos, pErrInfo); 1001 1002 return VERR_NOT_IMPLEMENTED; 1381 else if (enmOutType == RTFDTTYPE_DTB) 1382 return rtFdtDumpAsDtb(pThis, hVfsIos, pErrInfo); 1383 1384 return VERR_NOT_SUPPORTED; 1003 1385 } 1004 1386 … … 1009 1391 return VERR_NOT_IMPLEMENTED; 1010 1392 } 1393 1394 1395 RTDECL(int) RTFdtAddMemoryReservation(RTFDT hFdt, uint64_t PhysAddrStart, uint64_t cbArea) 1396 { 1397 PRTFDTINT pThis = hFdt; 1398 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1399 AssertReturn(PhysAddrStart > 0 || cbArea > 0, VERR_INVALID_PARAMETER); 1400 1401 if (pThis->cMemRsv == pThis->cMemRsvMax) 1402 { 1403 uint32_t cMemRsvMaxNew = pThis->cMemRsvMax + 10; 1404 PDTBFDTRSVENTRY paMemRsvNew = (PDTBFDTRSVENTRY)RTMemRealloc(pThis->paMemRsv, cMemRsvMaxNew * sizeof(*paMemRsvNew)); 1405 if (!paMemRsvNew) 1406 return VERR_NO_MEMORY; 1407 1408 pThis->paMemRsv = paMemRsvNew; 1409 pThis->cMemRsvMax = cMemRsvMaxNew; 1410 } 1411 1412 pThis->paMemRsv[pThis->cMemRsv].PhysAddrStart = PhysAddrStart; 1413 pThis->paMemRsv[pThis->cMemRsv].cbArea = cbArea; 1414 pThis->cMemRsv++; 1415 return VINF_SUCCESS; 1416 } 1417 1418 1419 RTDECL(int) RTFdtSetPhysBootCpuId(RTFDT hFdt, uint32_t idPhysBootCpu) 1420 { 1421 PRTFDTINT pThis = hFdt; 1422 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1423 1424 pThis->u32CpuIdPhysBoot = idPhysBootCpu; 1425 return VINF_SUCCESS; 1426 } 1427 1428 1429 RTDECL(int) RTFdtNodeAdd(RTFDT hFdt, const char *pszName) 1430 { 1431 PRTFDTINT pThis = hFdt; 1432 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1433 1434 /** @todo Validate node name against allowed character set. */ 1435 size_t cchName = strlen(pszName) + 1; 1436 int rc = rtFdtStructAppendTokenAndPayload(pThis, DTB_FDT_TOKEN_BEGIN_NODE_BE, pszName, cchName); 1437 if (RT_FAILURE(rc)) 1438 return rc; 1439 1440 pThis->cTreeDepth++; 1441 return VINF_SUCCESS; 1442 } 1443 1444 1445 RTDECL(int) RTFdtNodeAddF(RTFDT hFdt, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(2, 3) 1446 { 1447 va_list va; 1448 va_start(va, pszNameFmt); 1449 int rc = RTFdtNodeAddV(hFdt, pszNameFmt, va); 1450 va_end(va); 1451 return rc; 1452 } 1453 1454 1455 RTDECL(int) RTFdtNodeAddV(RTFDT hFdt, const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0) 1456 { 1457 char szName[512]; /* lazy developer */ 1458 ssize_t cch = RTStrPrintf2V(&szName[0], sizeof(szName), pszNameFmt, va); 1459 if (cch <= 0) 1460 return VERR_BUFFER_OVERFLOW; 1461 1462 return RTFdtNodeAdd(hFdt, &szName[0]); 1463 } 1464 1465 1466 RTDECL(int) RTFdtNodeFinalize(RTFDT hFdt) 1467 { 1468 PRTFDTINT pThis = hFdt; 1469 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1470 AssertReturn(pThis->cTreeDepth > 1, VERR_FDT_AT_ROOT_LEVEL); 1471 1472 int rc = rtFdtStructAppendTokenAndPayload(pThis, DTB_FDT_TOKEN_END_NODE_BE, NULL /*pvPayload*/, 0 /*cbPayload*/); 1473 if (RT_FAILURE(rc)) 1474 return rc; 1475 1476 pThis->cTreeDepth--; 1477 return VINF_SUCCESS; 1478 } 1479 1480 1481 RTDECL(int) RTFdtNodePropertyAddEmpty(RTFDT hFdt, const char *pszProperty) 1482 { 1483 PRTFDTINT pThis = hFdt; 1484 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1485 1486 return rtFdtStructAppendProperty(pThis, pszProperty, NULL /*pvProperty*/, 0 /*cbProperty*/); 1487 } 1488 1489 1490 RTDECL(int) RTFdtNodePropertyAddU32(RTFDT hFdt, const char *pszProperty, uint32_t u32) 1491 { 1492 PRTFDTINT pThis = hFdt; 1493 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1494 1495 RT_H2BE_U32(u32); 1496 return rtFdtStructAppendProperty(pThis, pszProperty, &u32, sizeof(u32)); 1497 } 1498 1499 1500 RTDECL(int) RTFdtNodePropertyAddString(RTFDT hFdt, const char *pszProperty, const char *pszVal) 1501 { 1502 PRTFDTINT pThis = hFdt; 1503 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1504 1505 uint32_t cchVal = (uint32_t)strlen(pszVal) + 1; 1506 return rtFdtStructAppendProperty(pThis, pszProperty, pszVal, cchVal); 1507 } 1508 1509 1510 RTDECL(int) RTFdtNodePropertyAddCellsU32(RTFDT hFdt, const char *pszProperty, uint32_t cCells, ...) 1511 { 1512 va_list va; 1513 va_start(va, cCells); 1514 int rc = RTFdtNodePropertyAddCellsU32V(hFdt, pszProperty, cCells, va); 1515 va_end(va); 1516 return rc; 1517 } 1518 1519 1520 RTDECL(int) RTFdtNodePropertyAddCellsU32V(RTFDT hFdt, const char *pszProperty, uint32_t cCells, va_list va) 1521 { 1522 PRTFDTINT pThis = hFdt; 1523 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1524 1525 /* Insert the property name into the strings block. */ 1526 uint32_t offStr; 1527 int rc = rtFdtStringsInsertString(pThis, pszProperty, &offStr); 1528 if (RT_FAILURE(rc)) 1529 return rc; 1530 1531 uint32_t cbPropAligned = RT_ALIGN_32(cCells * sizeof(uint32_t) + 3 * sizeof(uint32_t), sizeof(uint32_t)); 1532 1533 rc = rtFdtStructEnsureSpace(pThis, cbPropAligned); 1534 if (RT_FAILURE(rc)) 1535 return rc; 1536 1537 uint32_t *pu32 = (uint32_t *)(pThis->pbStruct + pThis->cbStruct); 1538 *pu32++ = DTB_FDT_TOKEN_PROPERTY_BE; 1539 *pu32++ = RT_H2BE_U32(cCells * sizeof(uint32_t)); 1540 *pu32++ = RT_H2BE_U32(offStr); 1541 for (uint32_t i = 0; i < cCells; i++) 1542 *pu32++ = va_arg(va, uint32_t); 1543 1544 pThis->cbStruct += cbPropAligned; 1545 return VINF_SUCCESS; 1546 }
Note:
See TracChangeset
for help on using the changeset viewer.