Changeset 98481 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Feb 7, 2023 9:52:23 AM (2 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevQemuFwCfg.cpp
r98103 r98481 46 46 * 47 47 * The only mandatory item is the KernelImage one, the others are optional if the 48 * kernel is configured to not require it. If the kernel is not an EFI compatible 49 * executable (CONFIG_EFI_STUB=y for Linux) a dedicated setup image might be required 48 * kernel is configured to not require it. The InitrdImage item accepts a path to a directory as well. 49 * If a directory is encountered, the CPIO initrd image is created on the fly and passed to the guest. 50 * If the kernel is not an EFI compatible executable (CONFIG_EFI_STUB=y for Linux) a dedicated setup image might be required 50 51 * which can be set with: 51 52 * … … 71 72 #include <iprt/errcore.h> 72 73 #include <iprt/assert.h> 74 #include <iprt/dir.h> 73 75 #include <iprt/file.h> 76 #include <iprt/path.h> 74 77 #include <iprt/string.h> 75 78 #include <iprt/vfs.h> 76 79 #include <iprt/zero.h> 80 #include <iprt/zip.h> 77 81 78 82 #include "VBoxDD.h" … … 147 151 /** @} */ 148 152 153 /** The size of the directory entry buffer we're using. */ 154 #define QEMUFWCFG_DIRENTRY_BUF_SIZE (sizeof(RTDIRENTRYEX) + RTPATH_MAX) 155 149 156 150 157 /********************************************************************************************************************************* … … 193 200 /** Guest physical address of the DMA descriptor. */ 194 201 RTGCPHYS GCPhysDma; 202 /** VFS file of the on-the-fly created initramfs. */ 203 RTVFSFILE hVfsFileInitrd; 195 204 196 205 /** Scratch buffer for config item specific data. */ … … 303 312 PCPDMDEVHLPR3 pHlp = pThis->pDevIns->pHlpR3; 304 313 305 /* Query the path from the CFGM key. */ 306 char *pszFilePath = NULL; 307 int rc = pHlp->pfnCFGMQueryStringAlloc(pThis->pCfg, pItem->pszCfgmKey, &pszFilePath); 314 int rc = VINF_SUCCESS; 315 RTVFSFILE hVfsFile = NIL_RTVFSFILE; 316 if ( pItem->uCfgItem == QEMU_FW_CFG_ITEM_INITRD_SIZE 317 && pThis->hVfsFileInitrd != NIL_RTVFSFILE) 318 { 319 RTVfsFileRetain(pThis->hVfsFileInitrd); 320 hVfsFile = pThis->hVfsFileInitrd; 321 } 322 else 323 { 324 /* Query the path from the CFGM key. */ 325 char *pszFilePath = NULL; 326 rc = pHlp->pfnCFGMQueryStringAlloc(pThis->pCfg, pItem->pszCfgmKey, &pszFilePath); 327 if (RT_SUCCESS(rc)) 328 { 329 rc = RTVfsFileOpenNormal(pszFilePath, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &hVfsFile); 330 if (RT_FAILURE(rc)) 331 LogRel(("QemuFwCfg: Failed to open file \"%s\" -> %Rrc\n", pszFilePath, rc)); 332 PDMDevHlpMMHeapFree(pThis->pDevIns, pszFilePath); 333 } 334 else 335 LogRel(("QemuFwCfg: Failed to query \"%s\" -> %Rrc\n", pItem->pszCfgmKey, rc)); 336 } 337 308 338 if (RT_SUCCESS(rc)) 309 339 { 310 RTVFSFILE hVfsFile = NIL_RTVFSFILE;311 rc = RTVfsFile OpenNormal(pszFilePath, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &hVfsFile);340 uint64_t cbFile = 0; 341 rc = RTVfsFileQuerySize(hVfsFile, &cbFile); 312 342 if (RT_SUCCESS(rc)) 313 343 { 314 uint64_t cbFile = 0; 315 rc = RTVfsFileQuerySize(hVfsFile, &cbFile); 316 if (RT_SUCCESS(rc)) 344 if (cbFile < _4G) 317 345 { 318 if (cbFile < _4G) 319 { 320 pThis->u.u32 = (uint32_t)cbFile; 321 *pcbItem = sizeof(uint32_t); 322 } 323 else 324 { 325 rc = VERR_BUFFER_OVERFLOW; 326 LogRel(("QemuFwCfg: File \"%s\" exceeds 4G limit (%llu)\n", pszFilePath, cbFile)); 327 } 346 pThis->u.u32 = (uint32_t)cbFile; 347 *pcbItem = sizeof(uint32_t); 328 348 } 329 349 else 330 LogRel(("QemuFwCfg: Failed to query file size from \"%s\" -> %Rrc\n", pszFilePath, rc)); 331 RTVfsFileRelease(hVfsFile); 350 { 351 rc = VERR_BUFFER_OVERFLOW; 352 LogRel(("QemuFwCfg: File exceeds 4G limit (%llu)\n", cbFile)); 353 } 332 354 } 333 355 else 334 LogRel(("QemuFwCfg: Failed to open file \"%s\" -> %Rrc\n", pszFilePath, rc)); 335 PDMDevHlpMMHeapFree(pThis->pDevIns, pszFilePath); 336 } 337 else 338 LogRel(("QemuFwCfg: Failed to query \"%s\" -> %Rrc\n", pItem->pszCfgmKey, rc)); 356 LogRel(("QemuFwCfg: Failed to query file size from -> %Rrc\n", rc)); 357 RTVfsFileRelease(hVfsFile); 358 } 339 359 340 360 return rc; … … 390 410 PCPDMDEVHLPR3 pHlp = pThis->pDevIns->pHlpR3; 391 411 392 /* Query the path from the CFGM key. */ 393 char *pszFilePath = NULL; 394 int rc = pHlp->pfnCFGMQueryStringAlloc(pThis->pCfg, pItem->pszCfgmKey, &pszFilePath); 412 int rc = VINF_SUCCESS; 413 if ( pItem->uCfgItem == QEMU_FW_CFG_ITEM_INITRD_DATA 414 && pThis->hVfsFileInitrd != NIL_RTVFSFILE) 415 { 416 RTVfsFileRetain(pThis->hVfsFileInitrd); 417 pThis->u.hVfsFile = pThis->hVfsFileInitrd; 418 } 419 else 420 { 421 /* Query the path from the CFGM key. */ 422 char *pszFilePath = NULL; 423 rc = pHlp->pfnCFGMQueryStringAlloc(pThis->pCfg, pItem->pszCfgmKey, &pszFilePath); 424 if (RT_SUCCESS(rc)) 425 { 426 rc = RTVfsFileOpenNormal(pszFilePath, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &pThis->u.hVfsFile); 427 if (RT_FAILURE(rc)) 428 LogRel(("QemuFwCfg: Failed to open file \"%s\" -> %Rrc\n", pszFilePath, rc)); 429 PDMDevHlpMMHeapFree(pThis->pDevIns, pszFilePath); 430 } 431 else 432 LogRel(("QemuFwCfg: Failed to query \"%s\" -> %Rrc\n", pItem->pszCfgmKey, rc)); 433 } 434 395 435 if (RT_SUCCESS(rc)) 396 436 { 397 rc = RTVfsFileOpenNormal(pszFilePath, RTFILE_O_READ | RTFILE_O_DENY_NONE | RTFILE_O_OPEN, &pThis->u.hVfsFile); 437 uint64_t cbFile = 0; 438 rc = RTVfsFileQuerySize(pThis->u.hVfsFile, &cbFile); 398 439 if (RT_SUCCESS(rc)) 399 440 { 400 uint64_t cbFile = 0;401 rc = RTVfsFileQuerySize(pThis->u.hVfsFile, &cbFile);402 if (RT_SUCCESS(rc))441 if (cbFile < _4G) 442 *pcbItem = (uint32_t)cbFile; 443 else 403 444 { 404 if (cbFile < _4G) 405 *pcbItem = (uint32_t)cbFile; 406 else 407 { 408 rc = VERR_BUFFER_OVERFLOW; 409 LogRel(("QemuFwCfg: File \"%s\" exceeds 4G limit (%llu)\n", pszFilePath, cbFile)); 410 } 445 rc = VERR_BUFFER_OVERFLOW; 446 LogRel(("QemuFwCfg: File exceeds 4G limit (%llu)\n", cbFile)); 411 447 } 412 else413 LogRel(("QemuFwCfg: Failed to query file size from \"%s\" -> %Rrc\n", pszFilePath, rc));414 448 } 415 449 else 416 LogRel(("QemuFwCfg: Failed to open file \"%s\" -> %Rrc\n", pszFilePath, rc)); 417 PDMDevHlpMMHeapFree(pThis->pDevIns, pszFilePath); 418 } 419 else 420 LogRel(("QemuFwCfg: Failed to query \"%s\" -> %Rrc\n", pItem->pszCfgmKey, rc)); 450 LogRel(("QemuFwCfg: Failed to query file size from -> %Rrc\n", rc)); 451 } 421 452 422 453 return rc; … … 762 793 763 794 /** 795 * Sets up the initrd memory file and CPIO filesystem stream for writing. 796 * 797 * @returns VBox status code. 798 * @param pThis The QEMU fw config device instance. 799 * @param phVfsFss Where to return the filesystem stream handle. 800 */ 801 static int qemuFwCfgCreateOutputArchive(PDEVQEMUFWCFG pThis, PRTVFSFSSTREAM phVfsFss) 802 { 803 int rc = RTVfsMemFileCreate(NIL_RTVFSIOSTREAM, 0 /*cbEstimate*/, &pThis->hVfsFileInitrd); 804 if (RT_SUCCESS(rc)) 805 { 806 RTVFSFSSTREAM hVfsFss; 807 RTVFSIOSTREAM hVfsIosOut = RTVfsFileToIoStream(pThis->hVfsFileInitrd); 808 rc = RTZipTarFsStreamToIoStream(hVfsIosOut, RTZIPTARFORMAT_CPIO_ASCII_NEW, 0 /*fFlags*/, &hVfsFss); 809 if (RT_SUCCESS(rc)) 810 { 811 rc = RTZipTarFsStreamSetOwner(hVfsFss, 0, "root"); 812 if (RT_SUCCESS(rc)) 813 rc = RTZipTarFsStreamSetGroup(hVfsFss, 0, "root"); 814 815 if (RT_SUCCESS(rc)) 816 *phVfsFss = hVfsFss; 817 else 818 { 819 RTVfsFsStrmRelease(hVfsFss); 820 *phVfsFss = NIL_RTVFSFSSTREAM; 821 } 822 } 823 RTVfsIoStrmRelease(hVfsIosOut); 824 } 825 826 return rc; 827 } 828 829 830 /** 831 * Archives a file. 832 * 833 * @returns VBox status code. 834 * @param hVfsFss The TAR filesystem stream handle. 835 * @param pszSrc The file path or VFS spec. 836 * @param pszDst The name to archive the file under. 837 * @param pErrInfo Error info buffer (saves stack space). 838 */ 839 static int qemuFwCfgInitrdArchiveFile(RTVFSFSSTREAM hVfsFss, const char *pszSrc, 840 const char *pszDst, PRTERRINFOSTATIC pErrInfo) 841 { 842 /* Open the file. */ 843 uint32_t offError; 844 RTVFSIOSTREAM hVfsIosSrc; 845 int rc = RTVfsChainOpenIoStream(pszSrc, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, 846 &hVfsIosSrc, &offError, RTErrInfoInitStatic(pErrInfo)); 847 if (RT_FAILURE(rc)) 848 return rc; 849 850 /* I/O stream to base object. */ 851 RTVFSOBJ hVfsObjSrc = RTVfsObjFromIoStream(hVfsIosSrc); 852 if (hVfsObjSrc != NIL_RTVFSOBJ) 853 { 854 /* 855 * Add it to the stream. 856 */ 857 rc = RTVfsFsStrmAdd(hVfsFss, pszDst, hVfsObjSrc, 0 /*fFlags*/); 858 RTVfsIoStrmRelease(hVfsIosSrc); 859 RTVfsObjRelease(hVfsObjSrc); 860 return rc; 861 } 862 RTVfsIoStrmRelease(hVfsIosSrc); 863 return VERR_INVALID_POINTER; 864 } 865 866 867 /** 868 * Archives a symlink. 869 * 870 * @returns VBox status code. 871 * @param hVfsFss The TAR filesystem stream handle. 872 * @param pszSrc The file path or VFS spec. 873 * @param pszDst The name to archive the file under. 874 * @param pErrInfo Error info buffer (saves stack space). 875 */ 876 static int qemuFwCfgInitrdArchiveSymlink(RTVFSFSSTREAM hVfsFss, const char *pszSrc, 877 const char *pszDst, PRTERRINFOSTATIC pErrInfo) 878 { 879 /* Open the file. */ 880 uint32_t offError; 881 RTVFSOBJ hVfsObjSrc; 882 int rc = RTVfsChainOpenObj(pszSrc, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, 883 RTVFSOBJ_F_OPEN_SYMLINK | RTVFSOBJ_F_CREATE_NOTHING | RTPATH_F_ON_LINK, 884 &hVfsObjSrc, &offError, RTErrInfoInitStatic(pErrInfo)); 885 if (RT_FAILURE(rc)) 886 return rc; 887 888 rc = RTVfsFsStrmAdd(hVfsFss, pszDst, hVfsObjSrc, 0 /*fFlags*/); 889 RTVfsObjRelease(hVfsObjSrc); 890 return rc; 891 } 892 893 894 /** 895 * Sub-directory helper for creating archives. 896 * 897 * @returns VBox status code. 898 * @param hVfsFss The TAR filesystem stream handle. 899 * @param pszSrc The directory path or VFS spec. We append to the 900 * buffer as we decend. 901 * @param cchSrc The length of the input. 902 * @param pszDst The name to archive it the under. We append to the 903 * buffer as we decend. 904 * @param cchDst The length of the input. 905 * @param pDirEntry Directory entry to use for the directory to handle. 906 * @param pErrInfo Error info buffer (saves stack space). 907 */ 908 static int qemuFwCfgInitrdArchiveDirSub(RTVFSFSSTREAM hVfsFss, 909 char *pszSrc, size_t cchSrc, 910 char pszDst[RTPATH_MAX], size_t cchDst, PRTDIRENTRYEX pDirEntry, 911 PRTERRINFOSTATIC pErrInfo) 912 { 913 uint32_t offError; 914 RTVFSDIR hVfsIoDir; 915 int rc = RTVfsChainOpenDir(pszSrc, 0 /*fFlags*/, 916 &hVfsIoDir, &offError, RTErrInfoInitStatic(pErrInfo)); 917 if (RT_FAILURE(rc)) 918 return rc; 919 920 /* Make sure we've got some room in the path, to save us extra work further down. */ 921 if (cchSrc + 3 >= RTPATH_MAX) 922 return VERR_FILENAME_TOO_LONG; 923 924 /* Ensure we've got a trailing slash (there is space for it see above). */ 925 if (!RTPATH_IS_SEP(pszSrc[cchSrc - 1])) 926 { 927 pszSrc[cchSrc++] = RTPATH_SLASH; 928 pszSrc[cchSrc] = '\0'; 929 } 930 931 /* Ditto for destination. */ 932 if (cchDst + 3 >= RTPATH_MAX) 933 return VERR_FILENAME_TOO_LONG; 934 935 /* Don't try adding the root directory. */ 936 if (*pszDst != '\0') 937 { 938 RTVFSOBJ hVfsObjSrc = RTVfsObjFromDir(hVfsIoDir); 939 rc = RTVfsFsStrmAdd(hVfsFss, pszDst, hVfsObjSrc, 0 /*fFlags*/); 940 RTVfsObjRelease(hVfsObjSrc); 941 if (RT_FAILURE(rc)) 942 return rc; 943 944 if (!RTPATH_IS_SEP(pszDst[cchDst - 1])) 945 { 946 pszDst[cchDst++] = RTPATH_SLASH; 947 pszDst[cchDst] = '\0'; 948 } 949 } 950 951 /* 952 * Process the files and subdirs. 953 */ 954 for (;;) 955 { 956 size_t cbDirEntry = QEMUFWCFG_DIRENTRY_BUF_SIZE; 957 rc = RTVfsDirReadEx(hVfsIoDir, pDirEntry, &cbDirEntry, RTFSOBJATTRADD_UNIX); 958 if (RT_FAILURE(rc)) 959 break; 960 961 /* Check length. */ 962 if (pDirEntry->cbName + cchSrc + 3 >= RTPATH_MAX) 963 { 964 rc = VERR_BUFFER_OVERFLOW; 965 break; 966 } 967 968 switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK) 969 { 970 case RTFS_TYPE_DIRECTORY: 971 { 972 if (RTDirEntryExIsStdDotLink(pDirEntry)) 973 continue; 974 975 memcpy(&pszSrc[cchSrc], pDirEntry->szName, pDirEntry->cbName + 1); 976 memcpy(&pszDst[cchDst], pDirEntry->szName, pDirEntry->cbName + 1); 977 rc = qemuFwCfgInitrdArchiveDirSub(hVfsFss, pszSrc, cchSrc + pDirEntry->cbName, 978 pszDst, cchDst + pDirEntry->cbName, pDirEntry, pErrInfo); 979 break; 980 } 981 982 case RTFS_TYPE_FILE: 983 { 984 memcpy(&pszSrc[cchSrc], pDirEntry->szName, pDirEntry->cbName + 1); 985 memcpy(&pszDst[cchDst], pDirEntry->szName, pDirEntry->cbName + 1); 986 rc = qemuFwCfgInitrdArchiveFile(hVfsFss, pszSrc, pszDst, pErrInfo); 987 break; 988 } 989 990 case RTFS_TYPE_SYMLINK: 991 { 992 memcpy(&pszSrc[cchSrc], pDirEntry->szName, pDirEntry->cbName + 1); 993 memcpy(&pszDst[cchDst], pDirEntry->szName, pDirEntry->cbName + 1); 994 rc = qemuFwCfgInitrdArchiveSymlink(hVfsFss, pszSrc, pszDst, pErrInfo); 995 break; 996 } 997 998 default: 999 { 1000 LogRel(("Warning: File system type %#x for '%s' not implemented yet, sorry! Skipping ...\n", 1001 pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK, pDirEntry->szName)); 1002 break; 1003 } 1004 } 1005 } 1006 1007 if (rc == VERR_NO_MORE_FILES) 1008 rc = VINF_SUCCESS; 1009 1010 RTVfsDirRelease(hVfsIoDir); 1011 return rc; 1012 } 1013 1014 1015 /** 1016 * Archives a directory recursively. 1017 * 1018 * @returns VBox status code. 1019 * @param hVfsFss The CPIO filesystem stream handle. 1020 * @param pszSrc The directory path or VFS spec. We append to the 1021 * buffer as we decend. 1022 * @param cchSrc The length of the input. 1023 * @param pszDst The name to archive it the under. We append to the 1024 * buffer as we decend. 1025 * @param cchDst The length of the input. 1026 * @param pErrInfo Error info buffer (saves stack space). 1027 */ 1028 static int qemuFwCfgInitrdArchiveDir(RTVFSFSSTREAM hVfsFss, char pszSrc[RTPATH_MAX], size_t cchSrc, 1029 char pszDst[RTPATH_MAX], size_t cchDst, 1030 PRTERRINFOSTATIC pErrInfo) 1031 { 1032 RT_NOREF(cchSrc); 1033 1034 char szSrcAbs[RTPATH_MAX]; 1035 int rc = RTPathAbs(pszSrc, szSrcAbs, sizeof(szSrcAbs)); 1036 if (RT_FAILURE(rc)) 1037 return rc; 1038 1039 union 1040 { 1041 uint8_t abPadding[QEMUFWCFG_DIRENTRY_BUF_SIZE]; 1042 RTDIRENTRYEX DirEntry; 1043 } uBuf; 1044 1045 return qemuFwCfgInitrdArchiveDirSub(hVfsFss, szSrcAbs, strlen(szSrcAbs), pszDst, cchDst, &uBuf.DirEntry, pErrInfo); 1046 } 1047 1048 1049 /** 1050 * Creates an on the fly initramfs for a given root directory. 1051 * 1052 * @returns VBox status code. 1053 * @param pThis The QEMU fw config device instance. 1054 * @param pszPath The path to work on. 1055 */ 1056 static int qemuFwCfgInitrdCreate(PDEVQEMUFWCFG pThis, const char *pszPath) 1057 { 1058 /* 1059 * First open the output file. 1060 */ 1061 RTVFSFSSTREAM hVfsFss; 1062 int rc = qemuFwCfgCreateOutputArchive(pThis, &hVfsFss); 1063 if (RT_FAILURE(rc)) 1064 return rc; 1065 1066 /* 1067 * Construct/copy the source name. 1068 */ 1069 char szSrc[RTPATH_MAX]; 1070 rc = RTStrCopy(szSrc, sizeof(szSrc), pszPath); 1071 if (RT_SUCCESS(rc)) 1072 { 1073 RTERRINFOSTATIC ErrInfo; 1074 char szDst[RTPATH_MAX]; RT_ZERO(szDst); 1075 rc = qemuFwCfgInitrdArchiveDir(hVfsFss, szSrc, strlen(szSrc), 1076 szDst, strlen(szDst), &ErrInfo); 1077 } 1078 1079 /* 1080 * Finalize the archive. 1081 */ 1082 int rc2 = RTVfsFsStrmEnd(hVfsFss); AssertRC(rc2); 1083 RTVfsFsStrmRelease(hVfsFss); 1084 return rc; 1085 } 1086 1087 1088 /** 1089 * Checks whether creation of the initrd should be done on the fly. 1090 * 1091 * @returns VBox status code. 1092 * @param pThis The QEMU fw config device instance. 1093 */ 1094 static int qemuFwCfgInitrdMaybeCreate(PDEVQEMUFWCFG pThis) 1095 { 1096 PPDMDEVINS pDevIns = pThis->pDevIns; 1097 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 1098 1099 /* Query the path from the CFGM key. */ 1100 char *pszFilePath = NULL; 1101 int rc = pHlp->pfnCFGMQueryStringAlloc(pThis->pCfg, "InitrdImage", &pszFilePath); 1102 if (RT_SUCCESS(rc)) 1103 { 1104 if (RTDirExists(pszFilePath)) 1105 { 1106 rc = qemuFwCfgInitrdCreate(pThis, pszFilePath); 1107 if (RT_FAILURE(rc)) 1108 rc = PDMDEV_SET_ERROR(pDevIns, rc, 1109 N_("QemuFwCfg: failed to create the in memory initram filesystem")); 1110 } 1111 /*else: Probably a normal file. */ 1112 PDMDevHlpMMHeapFree(pDevIns, pszFilePath); 1113 } 1114 else if (rc != VERR_CFGM_VALUE_NOT_FOUND) 1115 rc = PDMDEV_SET_ERROR(pDevIns, rc, 1116 N_("Configuration error: Querying \"InitrdImage\" as a string failed")); 1117 else 1118 rc = VINF_SUCCESS; 1119 1120 return rc; 1121 } 1122 1123 1124 /** 764 1125 * @interface_method_impl{PDMDEVREG,pfnReset} 765 1126 */ … … 770 1131 qemuFwCfgR3ItemReset(pThis); 771 1132 pThis->GCPhysDma = 0; 1133 1134 if (pThis->hVfsFileInitrd != NIL_RTVFSFILE) 1135 RTVfsFileRelease(pThis->hVfsFileInitrd); 1136 pThis->hVfsFileInitrd = NIL_RTVFSFILE; 1137 1138 qemuFwCfgInitrdMaybeCreate(pThis); /* Ignores status code. */ 772 1139 } 773 1140 … … 783 1150 qemuFwCfgR3ItemReset(pThis); 784 1151 pThis->GCPhysDma = 0; 1152 1153 if (pThis->hVfsFileInitrd != NIL_RTVFSFILE) 1154 RTVfsFileRelease(pThis->hVfsFileInitrd); 1155 pThis->hVfsFileInitrd = NIL_RTVFSFILE; 785 1156 786 1157 return VINF_SUCCESS; … … 820 1191 pThis->u32Version = QEMU_FW_CFG_VERSION_LEGACY | (fDmaEnabled ? QEMU_FW_CFG_VERSION_DMA : 0); 821 1192 pThis->GCPhysDma = 0; 1193 pThis->hVfsFileInitrd = NIL_RTVFSFILE; 822 1194 823 1195 qemuFwCfgR3ItemReset(pThis); 1196 1197 rc = qemuFwCfgInitrdMaybeCreate(pThis); 1198 if (RT_FAILURE(rc)) 1199 return rc; /* Error set. */ 824 1200 825 1201 /*
Note:
See TracChangeset
for help on using the changeset viewer.