Changeset 100022 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- May 31, 2023 8:40:43 AM (18 months ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/fdt.cpp
r100009 r100022 56 56 * Defined Constants And Macros * 57 57 *********************************************************************************************************************************/ 58 59 /** Special error token to denote that the end of the structs block was reached trying to query the next token. */ 60 #define RTFDT_TOKEN_ERROR UINT32_MAX 58 61 59 62 … … 80 83 /** Pointer to the internal Flattened Devicetree instance. */ 81 84 typedef RTFDTINT *PRTFDTINT; 85 86 87 /** 88 * DTB property dump callback. 89 * 90 * @returns IPRT status code. 91 * @param pThis Pointer to the FDT instance. 92 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 93 * @param pszProperty Property name. 94 * @param pvProperty Pointer to the raw property data. 95 * @param cbProperty Size of the property in bytes. 96 * @param pErrInfo Where to return additional error information. 97 */ 98 typedef DECLCALLBACKTYPE(int, FNRTFDTDTBPROPERTYDUMP,(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, const char *pszProperty, 99 const void *pvProperty, size_t cbProperty, PRTERRINFO pErrInfo)); 100 /** Pointer to a DTB property dump callback. */ 101 typedef FNRTFDTDTBPROPERTYDUMP *PFNRTFDTDTBPROPERTYDUMP; 102 103 104 /** 105 * DTB property dump descriptor. 106 */ 107 typedef struct RTFDTDTBPROPDUMPDESC 108 { 109 /** Name of the property. */ 110 const char *pszProperty; 111 /** The dump callback. */ 112 PFNRTFDTDTBPROPERTYDUMP pfnDump; 113 } RTFDTDTBPROPDUMPDESC; 114 /** Pointer to a property dump descriptor. */ 115 typedef RTFDTDTBPROPDUMPDESC *PRTFDTDTBPROPDUMPDESC; 116 /** Pointer to a const property dump descriptor. */ 117 typedef const RTFDTDTBPROPDUMPDESC *PCRTFDTDTBPROPDUMPDESC; 118 119 120 /** 121 * DTB struct dump state. 122 */ 123 typedef struct RTFDTDTBDUMP 124 { 125 /** Number of bytes left in the structs block to dump. */ 126 size_t cbLeft; 127 /** Pointer to the next item in the structs block. */ 128 const uint8_t *pbStructs; 129 } RTFDTDTBDUMP; 130 /** Pointer to a DTB struct dump state. */ 131 typedef RTFDTDTBDUMP *PRTFDTDTBDUMP; 132 /** Pointer to a constant DTB struct dump state. */ 133 typedef const RTFDTDTBDUMP *PCRTFDTDTBDUMP; 82 134 83 135 … … 163 215 if ( pDtbHdr->offDtStruct >= pDtbHdr->cbFdt 164 216 || (pDtbHdr->cbFdt - pDtbHdr->offDtStruct < pDtbHdr->cbDtStruct) 165 || pDtbHdr->offDtStruct < =pDtbHdr->offMemRsvMap + sizeof(DTBFDTRSVENTRY))217 || pDtbHdr->offDtStruct < pDtbHdr->offMemRsvMap + sizeof(DTBFDTRSVENTRY)) 166 218 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 219 pDtbHdr->offDtStruct, pDtbHdr->cbDtStruct, pDtbHdr->cbFdt, pDtbHdr->offMemRsvMap); … … 179 231 * Fres all resources allocated for the given FDT. 180 232 * 181 * @param pThis The FDT instance to destroy.233 * @param pThis Pointer to the FDT instance to destroy. 182 234 */ 183 235 static void rtFdtDestroy(PRTFDTINT pThis) … … 203 255 * 204 256 * @returns IPRT status code. 205 * @param pThis The FDT instance.257 * @param pThis Pointer to the FDT instance. 206 258 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 207 259 * @param pErrInfo Where to return additional error information. … … 234 286 break; 235 287 288 cMemRsv++; 289 236 290 /* 237 291 * The terminator must be included in the maximum entry count, if not 238 292 * the DTB is malformed and lacks a terminating entry before the start of the structs block. 239 293 */ 240 if (cMemRsv + 1== cMemRsvMax)294 if (cMemRsv == cMemRsvMax) 241 295 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_MEM_RSV_BLOCK_TERMINATOR_MISSING, 242 296 "The memory reservation block lacks a terminating entry"); 243 297 244 pThis->paMemRsv[cMemRsv].PhysAddrStart = RT_BE2H_U64(MemRsv.PhysAddrStart); 245 pThis->paMemRsv[cMemRsv].cbArea = RT_BE2H_U64(MemRsv.cbArea); 246 cMemRsv++; 298 pThis->paMemRsv[cMemRsv - 1].PhysAddrStart = RT_BE2H_U64(MemRsv.PhysAddrStart); 299 pThis->paMemRsv[cMemRsv - 1].cbArea = RT_BE2H_U64(MemRsv.cbArea); 247 300 } 248 301 249 pThis->cMemRsv = cMemRsv + 1;302 pThis->cMemRsv = cMemRsv; 250 303 return VINF_SUCCESS; 251 304 } … … 256 309 * 257 310 * @returns IPRT status code. 258 * @param pThis The FDT instance.311 * @param pThis Pointer to the FDT instance. 259 312 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 260 313 * @param pErrInfo Where to return additional error information. … … 267 320 pThis->DtbHdr.cbDtStruct); 268 321 269 int rc = RTVfsIoStrmRead(hVfsIos, pThis->pu32Structs, pThis->DtbHdr.cbDtStruct, true /*fBlocking*/, NULL /*pcbRead*/); 322 int rc = RTVfsIoStrmReadAt(hVfsIos, pThis->DtbHdr.offDtStruct, pThis->pu32Structs, pThis->DtbHdr.cbDtStruct, 323 true /*fBlocking*/, NULL /*pcbRead*/); 270 324 if (RT_FAILURE(rc)) 271 325 return RTErrInfoSetF(pErrInfo, rc, "Failed to read structs block from I/O stream"); … … 279 333 * 280 334 * @returns IPRT status code. 281 * @param pThis The FDT instance.335 * @param pThis Pointer to the FDT instance. 282 336 * @param hVfsIos The VFS I/O stream handle to load the DTB from. 283 337 * @param pErrInfo Where to return additional error information. … … 290 344 pThis->DtbHdr.cbDtStrings); 291 345 292 int rc = RTVfsIoStrmRead(hVfsIos, pThis->paszStrings, pThis->DtbHdr.cbDtStrings, true /*fBlocking*/, NULL /*pcbRead*/); 346 int rc = RTVfsIoStrmReadAt(hVfsIos, pThis->DtbHdr.offDtStrings, pThis->paszStrings, pThis->DtbHdr.cbDtStrings, 347 true /*fBlocking*/, NULL /*pcbRead*/); 293 348 if (RT_FAILURE(rc)) 294 349 return RTErrInfoSetF(pErrInfo, rc, "Failed to read strings block from I/O stream"); … … 296 351 /* Verify that the strings block is terminated. */ 297 352 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 te mrinated");353 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRINGS_BLOCK_NOT_TERMINATED, "The strings block is not zero terminated"); 299 354 300 355 return VINF_SUCCESS; … … 372 427 373 428 429 /** 430 * Returns the next token in the structs block from the given start returning an error 431 * if beyond the structs block. 432 * 433 * @returns Next token or RTFDT_TOKEN_ERROR if the end of the structs block is reached. 434 * @param pDump Pointer to the dump state. 435 */ 436 DECLINLINE(uint32_t) rtFdtStructsGetToken(PRTFDTDTBDUMP pDump) 437 { 438 if (pDump->cbLeft < sizeof(uint32_t)) 439 return RTFDT_TOKEN_ERROR; 440 441 uint32_t u32Token = *(const uint32_t *)pDump->pbStructs; 442 pDump->pbStructs += sizeof(uint32_t); 443 pDump->cbLeft -= sizeof(uint32_t); 444 return u32Token; 445 } 446 447 448 /** 449 * Gets the offset inside the structs block given from the current pointer. 450 * 451 * @returns Offset in bytes from the start of the structs block. 452 * @param pThis Pointer to the FDT instance. 453 * @param pDump Pointer to the dump state. 454 */ 455 DECLINLINE(uint32_t) rtFdtStructsGetOffset(PRTFDTINT pThis, PCRTFDTDTBDUMP pDump) 456 { 457 return pThis->DtbHdr.cbDtStruct - pDump->cbLeft - sizeof(uint32_t); 458 } 459 460 461 /** 462 * Advances the pointer inside the dump state by the given amount of bytes taking care of the alignment. 463 * 464 * @returns IPRT status code. 465 * @param pDump Pointer to the dump state. 466 * @param cbAdv How many bytes to advance. 467 * @param rcOob The status code to set if advancing goes beyond the end of the structs block. 468 */ 469 DECLINLINE(int) rtFdtStructsDumpAdvance(PRTFDTDTBDUMP pDump, uint32_t cbAdv, int rcOob) 470 { 471 /* Align the pointer to the next 32-bit boundary. */ 472 const uint8_t *pbStructsNew = RT_ALIGN_PT(pDump->pbStructs + cbAdv, sizeof(uint32_t), uint8_t *); 473 if (((uintptr_t)pbStructsNew - (uintptr_t)pDump->pbStructs) > pDump->cbLeft) 474 return rcOob; 475 476 pDump->pbStructs = pbStructsNew; 477 pDump->cbLeft -= (uintptr_t)pbStructsNew - (uintptr_t)pDump->pbStructs; 478 return VINF_SUCCESS; 479 } 480 481 482 /** 483 * Adds the proper indentation before a new line. 484 * 485 * @returns IPRT status code. 486 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 487 * @param uIndentLvl The level of indentation. 488 */ 489 static int rtFdtStructsDumpDtsIndent(RTVFSIOSTREAM hVfsIos, uint32_t uIndentLvl) 490 { 491 while (uIndentLvl--) 492 { 493 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, " "); 494 if (cch != 4) 495 return cch < 0 ? -cch : VERR_BUFFER_UNDERFLOW; 496 } 497 498 return VINF_SUCCESS; 499 } 500 501 502 /** 503 * Queries a zero terminated ASCII string from the current location inside the structs block. 504 * 505 * @returns IPRT status code. 506 * @param pDump The dump state. 507 * @param pszString The string buffer to copy the string to. 508 * @param cchStringMax Maximum size of the string buffer in characters (including the terminator). 509 * @param pErrInfo Where to return additional error information. 510 */ 511 static int rtFdtStructsQueryString(PRTFDTDTBDUMP pDump, char *pszString, size_t cchStringMax, PRTERRINFO pErrInfo) 512 { 513 const char *pszStrSrc = (const char *)pDump->pbStructs; 514 size_t cbLeft = pDump->cbLeft; 515 516 AssertReturn(cchStringMax, VERR_INTERNAL_ERROR); 517 518 for (;;) 519 { 520 *pszString++ = *pszStrSrc; 521 cchStringMax--; 522 cbLeft--; 523 524 if (*pszStrSrc == '\0') 525 { 526 pszStrSrc++; 527 528 int rc = rtFdtStructsDumpAdvance(pDump, (uintptr_t)pszStrSrc - (uintptr_t)pDump->pbStructs, VERR_FDT_DTB_STRUCTS_BLOCK_MALFORMED_PADDING); 529 if (RT_FAILURE(rc)) 530 return RTErrInfoSetF(pErrInfo, rc, "String end + padding exceeds structs block"); 531 532 return VINF_SUCCESS; 533 } 534 535 if (!cchStringMax) 536 return RTErrInfoSetF(pErrInfo, VERR_BUFFER_OVERFLOW, "Structs string too long to fit into target buffer"); 537 538 *pszStrSrc++; 539 if (!cbLeft) 540 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_STRING_NOT_TERMINATED, "Structs block contains an unterminated string"); 541 } 542 543 /* Not reached */ 544 return VERR_INTERNAL_ERROR; 545 } 546 547 548 /** 549 * Dumps a string list property. 550 * 551 * @returns IPRT status code. 552 * @param pThis Pointer to the FDT instance. 553 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 554 * @param pszProperty Name of the property being dumped. 555 * @param pvProperty Raw property payload. 556 * @param cbProperty Size of the property payload in bytes. 557 * @param pErrInfo Where to return additional error information. 558 */ 559 static DECLCALLBACK(int) rtFdtDtbPropDumpStringList(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, const char *pszProperty, 560 const void *pvProperty, size_t cbProperty, PRTERRINFO pErrInfo) 561 { 562 RT_NOREF(pThis); 563 564 const char *pszProp = (const char *)pvProperty; 565 if (pszProp[cbProperty - 1] != '\0') 566 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_PROP_STRING_NOT_TERMINATED, 567 "The string payload of property '%s' is not terminated", pszProperty); 568 569 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "\"%s\"", pszProp); 570 if (cch <= 0) 571 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write property data"); 572 573 cch = strlen(pszProp) + 1; 574 cbProperty -= cch; 575 while (cbProperty) 576 { 577 pszProp += cch; 578 579 cch = RTVfsIoStrmPrintf(hVfsIos, ", \"%s\"", pszProp); 580 if (cch <= 0) 581 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write property data"); 582 583 cch = strlen(pszProp) + 1; 584 cbProperty -= cch; 585 } 586 587 return VINF_SUCCESS; 588 } 589 590 591 /** 592 * Dumps a string property. 593 * 594 * @returns IPRT status code. 595 * @param pThis Pointer to the FDT instance. 596 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 597 * @param pszProperty Name of the property being dumped. 598 * @param pvProperty Raw property payload. 599 * @param cbProperty Size of the property payload in bytes. 600 * @param pErrInfo Where to return additional error information. 601 */ 602 static DECLCALLBACK(int) rtFdtDtbPropDumpString(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, const char *pszProperty, 603 const void *pvProperty, size_t cbProperty, PRTERRINFO pErrInfo) 604 { 605 RT_NOREF(pThis); 606 607 const char *pszProp = (const char *)pvProperty; 608 if (pszProp[cbProperty - 1] != '\0') 609 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_PROP_STRING_NOT_TERMINATED, 610 "The string payload of property '%s' is not terminated", pszProperty); 611 612 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "\"%s\"", pszProp); 613 if (cch <= 0) 614 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write property data"); 615 616 return VINF_SUCCESS; 617 } 618 619 620 /** 621 * Dumps a <u32> cell property. 622 * 623 * @returns IPRT status code. 624 * @param pThis Pointer to the FDT instance. 625 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 626 * @param pszProperty Name of the property being dumped. 627 * @param pvProperty Raw property payload. 628 * @param cbProperty Size of the property payload in bytes. 629 * @param pErrInfo Where to return additional error information. 630 */ 631 static DECLCALLBACK(int) rtFdtDtbPropDumpCellsU32(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, const char *pszProperty, 632 const void *pvProperty, size_t cbProperty, PRTERRINFO pErrInfo) 633 { 634 RT_NOREF(pThis); 635 636 if (cbProperty % sizeof(uint32_t)) 637 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_PROP_SIZE_MALFORMED, 638 "Property '%s' payload is not a multiple of 32-bit", pszProperty); 639 640 const uint32_t *pu32Prop = (const uint32_t *)pvProperty; 641 642 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "<"); 643 if (cch == 1) 644 { 645 cch = RTVfsIoStrmPrintf(hVfsIos, "%#RX32", RT_BE2H_U32(*pu32Prop)); 646 pu32Prop++; 647 if (cch > 0) 648 { 649 for (uint32_t i = 1; i < cbProperty / sizeof(uint32_t); i++) 650 { 651 cch = RTVfsIoStrmPrintf(hVfsIos, " %#RX32", RT_BE2H_U32(*pu32Prop)); 652 pu32Prop++; 653 if (cch <= 0) 654 break; 655 } 656 } 657 658 if (cch > 0) 659 cch = RTVfsIoStrmPrintf(hVfsIos, ">"); 660 } 661 662 if (cch <= 0) 663 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write property data"); 664 665 return VINF_SUCCESS; 666 } 667 668 669 /** 670 * The known properties to dump. 671 */ 672 static const RTFDTDTBPROPDUMPDESC g_aPropDump[] = 673 { 674 { "compatible", rtFdtDtbPropDumpStringList }, /** @todo stringlist */ 675 { "model", rtFdtDtbPropDumpString }, 676 { "status", rtFdtDtbPropDumpString }, 677 { "phandle", rtFdtDtbPropDumpCellsU32 }, 678 { "linux,phandle", rtFdtDtbPropDumpCellsU32 }, 679 { "#address-cells", rtFdtDtbPropDumpCellsU32 }, 680 { "#size-cells", rtFdtDtbPropDumpCellsU32 }, 681 { "reg", rtFdtDtbPropDumpCellsU32 }, 682 { "virtual-reg", rtFdtDtbPropDumpCellsU32 }, 683 { "ranges", rtFdtDtbPropDumpCellsU32 }, 684 { "dma-ranges", rtFdtDtbPropDumpCellsU32 }, 685 { "name", rtFdtDtbPropDumpString }, 686 { "device_type", rtFdtDtbPropDumpString }, 687 { "interrupts", rtFdtDtbPropDumpCellsU32 }, 688 { "interrupt-parent", rtFdtDtbPropDumpCellsU32 }, 689 { "interrupts-extended", rtFdtDtbPropDumpCellsU32 }, 690 { "#interrupt-cells", rtFdtDtbPropDumpCellsU32 }, 691 { "interrupt-map", rtFdtDtbPropDumpCellsU32 }, 692 { "interrupt-map-mask", rtFdtDtbPropDumpCellsU32 }, 693 { "serial-number", rtFdtDtbPropDumpString }, 694 { "chassis-type", rtFdtDtbPropDumpString }, 695 { "clock-frequency", rtFdtDtbPropDumpCellsU32 }, 696 { "reg-shift", rtFdtDtbPropDumpCellsU32 }, 697 { "label", rtFdtDtbPropDumpString }, 698 { "clock-names", rtFdtDtbPropDumpStringList }, 699 { "clock-output-names", rtFdtDtbPropDumpStringList }, 700 { "stdout-path", rtFdtDtbPropDumpString }, 701 { "method", rtFdtDtbPropDumpString }, 702 }; 703 704 705 /** 706 * Dumps the property as a DTS source starting at the given location inside the structs block. 707 * 708 * @returns IPRT status code. 709 * @param pThis Pointer to the FDT instance. 710 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 711 * @param pDump The dump state. 712 * @param uIndentLvl The level of indentation. 713 * @param pErrInfo Where to return additional error information. 714 */ 715 static int rtFdtStructsDumpPropertyAsDts(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTFDTDTBDUMP pDump, uint32_t uIndentLvl, PRTERRINFO pErrInfo) 716 { 717 DTBFDTPROP Prop; 718 719 if (pDump->cbLeft < sizeof(Prop)) 720 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_PREMATURE_END, 721 "Not enough space left in the structs block to read a property entry"); 722 723 memcpy(&Prop, pDump->pbStructs, sizeof(Prop)); 724 pDump->pbStructs += sizeof(Prop); 725 pDump->cbLeft -= sizeof(Prop); 726 Prop.offPropertyName = RT_BE2H_U32(Prop.offPropertyName); 727 Prop.cbProperty = RT_BE2H_U32(Prop.cbProperty); 728 729 if (Prop.offPropertyName >= pThis->DtbHdr.cbDtStrings) 730 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_PROP_NAME_OFF_TOO_LARGE, "Property name offset points past the string block"); 731 732 int rc = rtFdtStructsDumpDtsIndent(hVfsIos, uIndentLvl); 733 if (RT_FAILURE(rc)) 734 return rc; 735 736 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "%s", &pThis->paszStrings[Prop.offPropertyName]); 737 if (cch <= 0) 738 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write property name: '%s'", 739 &pThis->paszStrings[Prop.offPropertyName]); 740 741 const uint8_t *pbProp = pDump->pbStructs; 742 if (Prop.cbProperty) 743 { 744 if (Prop.cbProperty > pDump->cbLeft) 745 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_PREMATURE_END, "Property '%s' data exceeds struct blocks", 746 &pThis->paszStrings[Prop.offPropertyName]); 747 748 cch = RTVfsIoStrmPrintf(hVfsIos, " = "); 749 if (cch <= 0) 750 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to output property"); 751 752 rc = VERR_NOT_FOUND; 753 for (uint32_t i = 0; i < RT_ELEMENTS(g_aPropDump); i++) 754 { 755 if (!strcmp(g_aPropDump[i].pszProperty, &pThis->paszStrings[Prop.offPropertyName])) 756 { 757 rc = g_aPropDump[i].pfnDump(pThis, hVfsIos, &pThis->paszStrings[Prop.offPropertyName], 758 pbProp, Prop.cbProperty, pErrInfo); 759 break; 760 } 761 } 762 763 /* If not found use the standard U32 cells dumper. */ 764 if (rc == VERR_NOT_FOUND) 765 rc = rtFdtDtbPropDumpCellsU32(pThis, hVfsIos, &pThis->paszStrings[Prop.offPropertyName], 766 pbProp, Prop.cbProperty, pErrInfo); 767 if (RT_FAILURE(rc)) 768 return rc; 769 770 cch = RTVfsIoStrmPrintf(hVfsIos, ";\n"); 771 if (cch <= 0) 772 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to output property"); 773 774 rc = rtFdtStructsDumpAdvance(pDump, Prop.cbProperty, VERR_FDT_DTB_STRUCTS_BLOCK_PREMATURE_END); 775 } 776 else 777 { 778 cch = RTVfsIoStrmPrintf(hVfsIos, ";\n"); 779 if (cch <= 0) 780 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write newline"); 781 } 782 783 return rc; 784 } 785 786 787 /** 788 * Dumps the node name as a DTS source starting at the given location inside the structs block. 789 * 790 * @returns IPRT status code. 791 * @param pThis Pointer to the FDT instance. 792 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 793 * @param pDump The dump state. 794 * @param uIndentLvl The level of indentation. 795 * @param pErrInfo Where to return additional error information. 796 */ 797 static int rtFdtStructsDumpNodeAsDts(RTVFSIOSTREAM hVfsIos, PRTFDTDTBDUMP pDump, uint32_t uIndentLvl, PRTERRINFO pErrInfo) 798 { 799 char szNdName[512]; /* Should be plenty. */ 800 801 int rc = rtFdtStructsQueryString(pDump, &szNdName[0], sizeof(szNdName), pErrInfo); 802 if (RT_FAILURE(rc)) 803 return rc; 804 805 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "\n", szNdName); 806 if (cch <= 0) 807 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write DTS node name"); 808 809 rc = rtFdtStructsDumpDtsIndent(hVfsIos, uIndentLvl); 810 if (RT_FAILURE(rc)) 811 return rc; 812 813 cch = RTVfsIoStrmPrintf(hVfsIos, "%s {\n", szNdName); 814 if (cch <= 0) 815 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write DTS node name"); 816 817 return VINF_SUCCESS; 818 } 819 820 821 static int rtFdtStructsDumpEndNodeAsDts(RTVFSIOSTREAM hVfsIos, uint32_t uIndentLvl, PRTERRINFO pErrInfo) 822 { 823 int rc = rtFdtStructsDumpDtsIndent(hVfsIos, uIndentLvl); 824 if (RT_FAILURE(rc)) 825 return rc; 826 827 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "};\n"); 828 if (cch <= 0) 829 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write DTS node closing"); 830 831 return VINF_SUCCESS; 832 } 833 834 835 /** 836 * Dumps the given FDT as DTS v1 sources from the root node. 837 * 838 * @returns IPRT status code. 839 * @param pThis Pointer to the FDT instance. 840 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 841 * @param pErrInfo Where to return additional error information. 842 */ 843 static int rtFdtDumpRootAsDts(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 844 { 845 RTFDTDTBDUMP Dump; 846 847 Dump.cbLeft = pThis->DtbHdr.cbDtStruct; 848 Dump.pbStructs = (const uint8_t *)pThis->pu32Structs; 849 850 /* Skip any NOP tokens. */ 851 uint32_t u32Token = rtFdtStructsGetToken(&Dump); 852 while (u32Token == DTB_FDT_TOKEN_NOP_BE) 853 u32Token = rtFdtStructsGetToken(&Dump); 854 855 /* The root node starts with a BEGIN_NODE token. */ 856 if (u32Token != DTB_FDT_TOKEN_BEGIN_NODE_BE) 857 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_TOKEN_INVALID, "The structs block doesn't start with the BEGIN_NODE token for the root node: %#RX32", 858 RT_BE2H_U32(u32Token)); 859 860 /* Load the name for the root node (should be an empty string). */ 861 char chNdRootName; 862 int rc = rtFdtStructsQueryString(&Dump, &chNdRootName, sizeof(chNdRootName), pErrInfo); 863 if (RT_FAILURE(rc)) 864 return rc; 865 866 if (chNdRootName != '\0') 867 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_NODE_NAME_INVALID, "The root node name isn't zero terminated: %c", 868 chNdRootName); 869 870 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "/ {\n"); 871 if (cch <= 0) 872 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write DTS root node"); 873 874 uint32_t uNdLvl = 1; 875 u32Token = rtFdtStructsGetToken(&Dump); 876 while (u32Token != DTB_FDT_TOKEN_END_BE) 877 { 878 Log4(("rtFdtDumpAsDtsRoot: Token %#RX32 at offset %#RX32\n", RT_BE2H_U32(u32Token), rtFdtStructsGetOffset(pThis, &Dump))); 879 880 switch (u32Token) 881 { 882 case DTB_FDT_TOKEN_BEGIN_NODE_BE: 883 Log3(("rtFdtDumpAsDtsRoot: BEGIN_NODE token at offset %#RX32\n", rtFdtStructsGetOffset(pThis, &Dump))); 884 rc = rtFdtStructsDumpNodeAsDts(hVfsIos, &Dump, uNdLvl, pErrInfo); 885 if (RT_FAILURE(rc)) 886 return rc; 887 888 uNdLvl++; 889 break; 890 case DTB_FDT_TOKEN_PROPERTY_BE: 891 Log3(("rtFdtDumpAsDtsRoot: PROP token at offset %#RX32\n", rtFdtStructsGetOffset(pThis, &Dump))); 892 rc = rtFdtStructsDumpPropertyAsDts(pThis, hVfsIos, &Dump, uNdLvl, pErrInfo); 893 if (RT_FAILURE(rc)) 894 return rc; 895 break; 896 case DTB_FDT_TOKEN_NOP_BE: 897 Log3(("rtFdtDumpAsDtsRoot: NOP token at offset %#RX32\n", rtFdtStructsGetOffset(pThis, &Dump))); 898 break; 899 case DTB_FDT_TOKEN_END_NODE_BE: 900 Log3(("rtFdtDumpAsDtsRoot: END_NODE token at offset %#RX32\n", rtFdtStructsGetOffset(pThis, &Dump))); 901 if (!uNdLvl) 902 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_PREMATURE_END, 903 "END_NODE token encountered at the root node"); 904 905 uNdLvl--; 906 rc = rtFdtStructsDumpEndNodeAsDts(hVfsIos, uNdLvl, pErrInfo); 907 if (RT_FAILURE(rc)) 908 return rc; 909 break; 910 case RTFDT_TOKEN_ERROR: 911 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_TOKEN_INVALID, "The structs block is malformed"); 912 default: 913 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_TOKEN_INVALID, "The structs block contains an invalid/unknown token: %#RX32", 914 RT_BE2H_U32(u32Token)); 915 } 916 917 u32Token = rtFdtStructsGetToken(&Dump); 918 if (u32Token == DTB_FDT_TOKEN_END_BE) 919 Log3(("rtFdtDumpAsDtsRoot: END token at offset %#RX32\n", rtFdtStructsGetOffset(pThis, &Dump))); 920 } 921 922 /* Need to end on an END token. */ 923 if (u32Token != DTB_FDT_TOKEN_END_BE) 924 return RTErrInfoSetF(pErrInfo, VERR_FDT_DTB_STRUCTS_BLOCK_TOKEN_INVALID, "The structs block doesn't end with an END token (got %#RX32, expected %#RX32)", 925 RT_BE2H_U32(u32Token), DTB_FDT_TOKEN_END); 926 927 return VINF_SUCCESS; 928 } 929 930 931 /** 932 * Dumps the given FDT instance as DTS source. 933 * 934 * @returns IPRT status code. 935 * @param pThis Pointer to the FDT instance. 936 * @param hVfsIos The VFS I/O stream handle to dump the DTS to. 937 * @param pErrInfo Where to return additional error information. 938 */ 939 static int rtFdtDumpAsDts(PRTFDTINT pThis, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 940 { 941 ssize_t cch = RTVfsIoStrmPrintf(hVfsIos, "/dts-v1/;\n"); 942 if (cch <= 0) 943 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write DTS header"); 944 945 /* Write memory reservations. */ 946 for (uint32_t i = 0; i < pThis->cMemRsv; i++) 947 { 948 cch = RTVfsIoStrmPrintf(hVfsIos, "/memreserve/ %#RX64 %#RX64;\n", pThis->paMemRsv[i].PhysAddrStart, pThis->paMemRsv[i].cbArea); 949 if (cch <= 0) 950 return RTErrInfoSetF(pErrInfo, cch == 0 ? VERR_NO_MEMORY : -cch, "Failed to write memory reervation block %u", i); 951 } 952 953 /* Dump the tree. */ 954 return rtFdtDumpRootAsDts(pThis, hVfsIos, pErrInfo); 955 } 956 957 374 958 RTDECL(int) RTFdtCreateEmpty(PRTFDT phFdt) 375 959 { … … 407 991 408 992 409 RTDECL(int) RTFdtDumpToVfsIoStrm(RTFDT hFdt, RTFDTTYPE enmOutType, uint32_t fFlags, RTVFSIOSTREAM hVfsIos) 410 { 411 RT_NOREF(hFdt, enmOutType, fFlags, hVfsIos); 993 RTDECL(int) RTFdtDumpToVfsIoStrm(RTFDT hFdt, RTFDTTYPE enmOutType, uint32_t fFlags, RTVFSIOSTREAM hVfsIos, PRTERRINFO pErrInfo) 994 { 995 PRTFDTINT pThis = hFdt; 996 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 997 998 RT_NOREF(fFlags); 999 if (enmOutType == RTFDTTYPE_DTS) 1000 return rtFdtDumpAsDts(pThis, hVfsIos, pErrInfo); 1001 412 1002 return VERR_NOT_IMPLEMENTED; 413 1003 } 414 1004 415 1005 416 RTDECL(int) RTFdtDumpToFile(RTFDT hFdt, RTFDTTYPE enmOutType, uint32_t fFlags, const char *pszFilename )417 { 418 RT_NOREF(hFdt, enmOutType, fFlags, pszFilename );1006 RTDECL(int) RTFdtDumpToFile(RTFDT hFdt, RTFDTTYPE enmOutType, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo) 1007 { 1008 RT_NOREF(hFdt, enmOutType, fFlags, pszFilename, pErrInfo); 419 1009 return VERR_NOT_IMPLEMENTED; 420 1010 } -
trunk/src/VBox/Runtime/tools/RTDtc.cpp
r100006 r100022 206 206 if (RT_SUCCESS(rc)) 207 207 { 208 rc = RTFdtDumpToVfsIoStrm(hFdt, pOpts->enmOutType, 0 /*fFlags*/, hVfsIosDst); 209 if (RT_FAILURE(rc)) 208 rc = RTFdtDumpToVfsIoStrm(hFdt, pOpts->enmOutType, 0 /*fFlags*/, hVfsIosDst, RTErrInfoInitStatic(&ErrInfo)); 209 if (RT_FAILURE(rc) && RTErrInfoIsSet(&ErrInfo.Core)) 210 rc = RTMsgErrorRc(rc, "Writing the devicetree failed: %Rrc - %s", rc, ErrInfo.Core.pszMsg); 211 else if (RT_FAILURE(rc)) 210 212 rc = RTMsgErrorRc(rc, "Writing the devicetree failed: %Rrc\n", rc); 211 213 RTVfsIoStrmRelease(hVfsIosDst); 212 214 } 213 215 RTFdtDestroy(hFdt); 216 } 217 else 218 { 219 if (RTErrInfoIsSet(&ErrInfo.Core)) 220 rc = RTMsgErrorRc(rc, "Loading the devicetree blob failed: %Rrc - %s", rc, ErrInfo.Core.pszMsg); 221 else 222 rc = RTMsgErrorRc(rc, "Loading the devicetree blob failed: %Rrc\n", rc); 214 223 } 215 224 … … 275 284 if (rcExit2 != RTEXITCODE_SUCCESS) 276 285 rcExit = rcExit2; 286 fContinue = false; 277 287 break; 278 288 } … … 287 297 break; 288 298 299 case 'o': 300 Opts.pszOutFile = ValueUnion.psz; 301 break; 302 289 303 case 'O': 290 304 Opts.enmOutType = rtCmdDtcParseOutputType(ValueUnion.psz);
Note:
See TracChangeset
for help on using the changeset viewer.