Changeset 81647 in vbox for trunk/src/VBox/Devices/EFI
- Timestamp:
- Nov 4, 2019 11:38:14 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 134405
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/Firmware/VBoxPkg/VBoxApfsJmpStartDxe/VBoxApfsJmpStartDxe.c
r81604 r81647 44 44 #include <iprt/formats/apfs.h> 45 45 46 #define APFS_EFI_JMP_START_EXTENTS_MAX 3247 48 46 /** 49 47 * Contains the full jump start context being worked on. … … 59 57 /** Controller handle. */ 60 58 EFI_HANDLE hController; 61 /** Full jump start structure. */ 62 struct 63 { 64 APFSEFIJMPSTART Hdr; 65 APFSPRANGE aExtents[APFS_EFI_JMP_START_EXTENTS_MAX]; 66 } JmpStart; 59 /** APFS UUID. */ 60 APFSUUID Uuid; 67 61 } APFSJMPSTARTCTX; 68 62 typedef APFSJMPSTARTCTX *PAPFSJMPSTARTCTX; 69 63 typedef const APFSJMPSTARTCTX *PCAPFSJMPSTARTCTX; 70 64 71 #if 072 65 static EFI_GUID g_ApfsDrvLoadedFromThisControllerGuid = { 0x01aaf8bc, 0x9c37, 0x4dc1, 73 66 { 0xb1, 0x68, 0xe9, 0x67, 0xd4, 0x2c, 0x79, 0x25 } }; 74 #else75 static EFI_GUID g_ApfsDrvLoadedFromThisControllerGuid = { 0x03B8D751, 0xA02F, 0x4FF8,76 { 0x9B, 0x1A, 0x55, 0x24, 0xAF, 0xA3, 0x94, 0x5F } };77 #endif78 67 79 68 typedef struct APFS_DRV_LOADED_INFO … … 109 98 } 110 99 100 /** 101 * Calculates the fletcher64 checksum of the given APFS block and returns TRUE if it matches the one given in the object header. 102 * 103 * @returns Flag indicating whether the checksum matched. 104 * @param pObjHdr The object header containing the checksum to check against. 105 * @param pvStruct Pointer to the struct to create the checksum of. 106 * @param cbStruct Size of the struct in bytes. 107 */ 111 108 static BOOLEAN vboxApfsObjPhysIsChksumValid(PCAPFSOBJPHYS pObjHdr, void *pvStruct, size_t cbStruct) 112 109 { 113 return TRUE; /** @todo Checksum */ 114 } 115 116 static EFI_STATUS vboxApfsJmpStartLoadAndExecEfiDriver(IN PAPFSJMPSTARTCTX pCtx, IN PCAPFSNXSUPERBLOCK pSb) 117 { 118 UINTN cbReadLeft = RT_LE2H_U32(pCtx->JmpStart.Hdr.cbEfiFile); 110 if (cbStruct % sizeof(uint32_t) == 0) 111 { 112 uint32_t *pu32Data = (uint32_t *)pvStruct + 2; /* Start after the checksum field at the beginning. */ 113 size_t cWordsLeft = (cbStruct >> 2) - 2; 114 115 uint64_t u64C0 = 0; 116 uint64_t u64C1 = 0; 117 uint64_t u64ChksumFletcher64 = 0; 118 uint64_t u64Check0 = 0; 119 uint64_t u64Check1 = 0; 120 121 while (cWordsLeft) 122 { 123 u64C0 += (uint64_t)*pu32Data++; 124 u64C0 %= UINT32_C(0xffffffff); 125 126 u64C1 += u64C0; 127 u64C1 %= UINT32_C(0xffffffff); 128 129 cWordsLeft--; 130 } 131 132 u64Check0 = UINT32_C(0xffffffff) - (u64C0 + u64C1) % UINT32_C(0xffffffff); 133 u64Check1 = UINT32_C(0xffffffff) - (u64C0 + u64Check0) % UINT32_C(0xffffffff); 134 135 u64ChksumFletcher64 = (uint64_t)u64Check1 << 32 | u64Check0; 136 if (!CompareMem(&u64ChksumFletcher64, &pObjHdr->abChkSum[0], sizeof(pObjHdr->abChkSum))) 137 return TRUE; 138 else 139 DEBUG((DEBUG_INFO, "vboxApfsObjPhysIsChksumValid: Checksum mismatch, expected 0x%llx got 0x%llx", u64ChksumFletcher64, *(uint64_t *)&pObjHdr->abChkSum[0])); 140 } 141 else 142 DEBUG((DEBUG_INFO, "vboxApfsObjPhysIsChksumValid: Structure not a multiple of 32bit\n")); 143 144 return FALSE; 145 } 146 147 /** 148 * Loads and starts the EFI driver contained in the given jump start structure. 149 * 150 * @returns EFI status code. 151 * @param pCtx APFS jump start driver context structure. 152 * @param pJmpStart APFS jump start structure describing the EFI file to load and start. 153 */ 154 static EFI_STATUS vboxApfsJmpStartLoadAndExecEfiDriver(IN PAPFSJMPSTARTCTX pCtx, IN PCAPFSEFIJMPSTART pJmpStart) 155 { 156 PCAPFSPRANGE paExtents = (PCAPFSPRANGE)(pJmpStart + 1); 157 UINTN cbReadLeft = RT_LE2H_U32(pJmpStart->cbEfiFile); 119 158 EFI_STATUS rc = EFI_SUCCESS; 120 159 … … 125 164 uint8_t *pbBuf = (uint8_t *)pvApfsDrv; 126 165 127 for (i = 0; i < RT_LE2H_U32(p Ctx->JmpStart.Hdr.cExtents) && !EFI_ERROR(rc) && cbReadLeft; i++)166 for (i = 0; i < RT_LE2H_U32(pJmpStart->cExtents) && !EFI_ERROR(rc) && cbReadLeft; i++) 128 167 { 129 PCAPFSPRANGE pRange = &pCtx->JmpStart.aExtents[i]; 130 UINTN cbRead = RT_MIN(cbReadLeft, (UINTN)RT_LE2H_U64(pRange->cBlocks) * pCtx->cbBlock); 131 132 rc = vboxApfsJmpStartRead(pCtx, RT_LE2H_U64(pRange->PAddrStart), pbBuf, cbRead); 168 UINTN cbRead = RT_MIN(cbReadLeft, (UINTN)RT_LE2H_U64(paExtents[i].cBlocks) * pCtx->cbBlock); 169 170 rc = vboxApfsJmpStartRead(pCtx, RT_LE2H_U64(paExtents[i].PAddrStart), pbBuf, cbRead); 133 171 pbBuf += cbRead; 134 172 cbReadLeft -= cbRead; … … 147 185 148 186 rc = gBS->LoadImage(FALSE, gImageHandle, ParentDevicePath, 149 pvApfsDrv, RT_LE2H_U32(p Ctx->JmpStart.Hdr.cbEfiFile),187 pvApfsDrv, RT_LE2H_U32(pJmpStart->cbEfiFile), 150 188 &hImage); 151 189 if (!EFI_ERROR(rc)) … … 159 197 { 160 198 pApfsDrvLoadedInfo->hController = pCtx->hController; 161 CopyMem(&pApfsDrvLoadedInfo->GuidContainer, &p Sb->Uuid, sizeof(pApfsDrvLoadedInfo->GuidContainer));199 CopyMem(&pApfsDrvLoadedInfo->GuidContainer, &pCtx->Uuid, sizeof(pApfsDrvLoadedInfo->GuidContainer)); 162 200 163 201 rc = gBS->InstallMultipleProtocolInterfaces(&pCtx->hController, &g_ApfsDrvLoadedFromThisControllerGuid, pApfsDrvLoadedInfo, NULL); … … 165 203 { 166 204 /* Connect the driver with the controller it came from. */ 167 #if 0168 205 EFI_HANDLE ahImage[2]; 169 206 170 207 ahImage[0] = hImage; 171 208 ahImage[1] = NULL; 172 #endif 173 gBS->ConnectController(pCtx->hController, NULL /*&ahImage[0]*/, NULL, TRUE);209 210 gBS->ConnectController(pCtx->hController, &ahImage[0], NULL, TRUE); 174 211 return EFI_SUCCESS; 175 212 } … … 284 321 rc = vboxApfsJmpStartRead(&Ctx, 0, &Sb, sizeof(Sb)); 285 322 if ( !EFI_ERROR(rc) 286 && RT_LE2H_U32(Sb.u32Magic) == APFS_NX_SUPERBLOCK_MAGIC 287 && RT_LE2H_U64(Sb.PAddrEfiJmpStart) > 0 288 && vboxApfsObjPhysIsChksumValid(&Sb.ObjHdr, &Sb, sizeof(Sb))) 323 && RT_LE2H_U32(Sb.u32Magic) == APFS_NX_SUPERBLOCK_MAGIC) 289 324 { 290 Ctx.cbBlock = RT_LE2H_U32(Sb.cbBlock); 291 292 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: Found APFS superblock, reading jumpstart structure from %llx\n", RT_LE2H_U64(Sb.PAddrEfiJmpStart))); 293 rc = vboxApfsJmpStartRead(&Ctx, RT_LE2H_U64(Sb.PAddrEfiJmpStart), &Ctx.JmpStart, sizeof(Ctx.JmpStart)); 294 if ( !EFI_ERROR(rc) 295 && RT_H2LE_U32(Ctx.JmpStart.Hdr.u32Magic) == APFS_EFIJMPSTART_MAGIC 296 && RT_H2LE_U32(Ctx.JmpStart.Hdr.u32Version) == APFS_EFIJMPSTART_VERSION 297 && vboxApfsObjPhysIsChksumValid(&Ctx.JmpStart.Hdr.ObjHdr, &Ctx.JmpStart.Hdr, sizeof(Ctx.JmpStart.Hdr)) 298 && RT_H2LE_U32(Ctx.JmpStart.Hdr.cExtents) <= APFS_EFI_JMP_START_EXTENTS_MAX) 299 rc = vboxApfsJmpStartLoadAndExecEfiDriver(&Ctx, &Sb); 325 uint8_t *pbBlock = (uint8_t *)AllocateZeroPool(RT_LE2H_U32(Sb.cbBlock)); 326 327 if (pbBlock) 328 { 329 PCAPFSNXSUPERBLOCK pSb = (PCAPFSNXSUPERBLOCK)pbBlock; 330 331 /* Read in the complete block (checksums always cover the whole block and not just the structure...). */ 332 Ctx.cbBlock = RT_LE2H_U32(Sb.cbBlock); 333 334 rc = vboxApfsJmpStartRead(&Ctx, 0, pbBlock, Ctx.cbBlock); 335 if ( !EFI_ERROR(rc) 336 && RT_LE2H_U64(Sb.PAddrEfiJmpStart) > 0 337 && vboxApfsObjPhysIsChksumValid(&pSb->ObjHdr, pbBlock, Ctx.cbBlock)) 338 { 339 PCAPFSEFIJMPSTART pJmpStart = (PCAPFSEFIJMPSTART)pbBlock; 340 341 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: Found APFS superblock, reading jumpstart structure from %llx\n", RT_LE2H_U64(Sb.PAddrEfiJmpStart))); 342 343 CopyMem(&Ctx.Uuid, &pSb->Uuid, sizeof(Ctx.Uuid)); 344 345 rc = vboxApfsJmpStartRead(&Ctx, RT_LE2H_U64(Sb.PAddrEfiJmpStart), pbBlock, Ctx.cbBlock); 346 if ( !EFI_ERROR(rc) 347 && RT_H2LE_U32(pJmpStart->u32Magic) == APFS_EFIJMPSTART_MAGIC 348 && RT_H2LE_U32(pJmpStart->u32Version) == APFS_EFIJMPSTART_VERSION 349 && vboxApfsObjPhysIsChksumValid(&pJmpStart->ObjHdr, pbBlock, Ctx.cbBlock) 350 && RT_H2LE_U32(pJmpStart->cExtents) <= (Ctx.cbBlock - sizeof(*pJmpStart)) / sizeof(APFSPRANGE)) 351 rc = vboxApfsJmpStartLoadAndExecEfiDriver(&Ctx, pJmpStart); 352 else 353 { 354 rc = EFI_UNSUPPORTED; 355 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: The APFS EFI jumpstart structure is invalid\n")); 356 } 357 } 358 else 359 { 360 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: Invalid APFS superblock -> no APFS filesystem (%r %x %llx)\n", rc, Sb.u32Magic, Sb.PAddrEfiJmpStart)); 361 rc = EFI_UNSUPPORTED; 362 } 363 364 FreePool(pbBlock); 365 } 300 366 else 301 { 302 rc = EFI_UNSUPPORTED; 303 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: The APFS EFI jumpstart structure is invalid\n")); 304 } 367 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: Failed to allocate memory for APFS block data (%u bytes)\n", RT_LE2H_U32(Sb.cbBlock))); 305 368 } 306 369 else 307 { 308 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: Invalid APFS superblock -> no APFS filesystem (%r %x %llx)\n", rc, Sb.u32Magic, Sb.PAddrEfiJmpStart)); 309 rc = EFI_UNSUPPORTED; 310 } 370 DEBUG((DEBUG_INFO, "VBoxApfsJmpStart: Invalid APFS superblock -> no APFS filesystem (%r %x)\n", rc, Sb.u32Magic)); 311 371 312 372 gBS->CloseProtocol(ControllerHandle,
Note:
See TracChangeset
for help on using the changeset viewer.