16#include <Library/BaseLib.h>
17#include <Library/BaseMemoryLib.h>
18#include <Library/BaseOverflowLib.h>
19#include <Library/DebugLib.h>
20#include <Library/MemoryAllocationLib.h>
44 ASSERT (DataSize %
sizeof (UINT32) == 0);
50 WalkerEnd = Walker + DataSize /
sizeof (UINT32);
55 while (Walker < WalkerEnd) {
83 return (Sum1 << 32U) | Sum2;
95 ASSERT (DataSize >
sizeof (*Block));
102 if (NewChecksum == Block->
Checksum) {
106 DEBUG ((DEBUG_INFO,
"OCJS: Checksum mismatch for %Lx\n", Block->
ObjectOid));
119 EFI_BLOCK_IO_PROTOCOL *BlockIo;
126 if (PrivateData->EfiJumpStart == 0) {
127 DEBUG ((DEBUG_INFO,
"OCJS: Missing JumpStart for %g\n", &PrivateData->LocationInfo.ContainerUuid));
128 return EFI_UNSUPPORTED;
134 JumpStart = AllocateZeroPool (PrivateData->ApfsBlockSize);
135 if (JumpStart == NULL) {
136 return EFI_OUT_OF_RESOURCES;
144 Status = BlockIo->ReadBlocks (
146 BlockIo->Media->MediaId,
148 PrivateData->ApfsBlockSize,
154 "OCJS: Block (P:%d|F:%d) read req %Lx -> %Lx of %x (mask %u, mul %u) - %r\n",
155 BlockIo == PrivateData->BlockIo,
156 PrivateData->IsFusion,
157 PrivateData->EfiJumpStart,
159 PrivateData->ApfsBlockSize,
160 PrivateData->FusionMask,
161 PrivateData->LbaMultiplier,
165 if (EFI_ERROR (Status)) {
166 FreePool (JumpStart);
176 FreePool (JumpStart);
177 return EFI_UNSUPPORTED;
184 FreePool (JumpStart);
185 return EFI_UNSUPPORTED;
191 MaxExtents = (PrivateData->ApfsBlockSize -
sizeof (*JumpStart)) /
sizeof (JumpStart->
RecordExtents[0]);
192 if (MaxExtents < JumpStart->NumExtents) {
193 DEBUG ((DEBUG_INFO,
"OCJS: Invalid extent count %u / %u\n", JumpStart->
NumExtents, MaxExtents));
194 FreePool (JumpStart);
195 return EFI_UNSUPPORTED;
198 *JumpStartPtr = JumpStart;
207 OUT UINT32 *DriverSize,
208 OUT VOID **DriverBuffer
214 UINTN OrgEfiFileSize;
218 EFI_BLOCK_IO_PROTOCOL *BlockIo;
221 EfiFileSize = JumpStart->
EfiFileLen / PrivateData->ApfsBlockSize + 1;
222 if (BaseOverflowMulUN (EfiFileSize, PrivateData->ApfsBlockSize, &EfiFileSize)) {
223 return EFI_SECURITY_VIOLATION;
226 OrgEfiFileSize = EfiFileSize;
228 EfiFile = AllocateZeroPool (EfiFileSize);
229 if (EfiFile == NULL) {
230 return EFI_OUT_OF_RESOURCES;
235 for (Index = 0; Index < JumpStart->NumExtents || EfiFileSize != 0; ++Index) {
238 JumpStart->RecordExtents[Index].StartPhysicalAddr,
242 if ( (JumpStart->RecordExtents[Index].BlockCount > MAX_UINTN)
243 || BaseOverflowMulUN ((UINTN)JumpStart->RecordExtents[Index].BlockCount, PrivateData->ApfsBlockSize, &ChunkSize)
244 || (ChunkSize > EfiFileSize))
247 return EFI_SECURITY_VIOLATION;
250 Status = BlockIo->ReadBlocks (
252 BlockIo->Media->MediaId,
258 if (EFI_ERROR (Status)) {
263 ChunkPtr += ChunkSize;
264 EfiFileSize -= ChunkSize;
270 if (OrgEfiFileSize != JumpStart->EfiFileLen) {
272 ChunkPtr += JumpStart->EfiFileLen;
273 ZeroMem (ChunkPtr, OrgEfiFileSize - JumpStart->EfiFileLen);
276 *DriverSize = JumpStart->EfiFileLen;
277 *DriverBuffer = EfiFile;
284 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
304 for (Retry = 0; Retry < 2; ++Retry) {
308 SuperBlock = AllocateZeroPool (ReadSize);
309 if (SuperBlock == NULL) {
316 Status = BlockIo->ReadBlocks (
318 BlockIo->Media->MediaId,
323 if (EFI_ERROR (Status)) {
329 "OCJS: Testing disk with %8X magic %u block\n",
347 if ( (SuperBlock->
BlockSize < BlockIo->Media->BlockSize)
348 || ((SuperBlock->
BlockSize & (BlockIo->Media->BlockSize - 1)) != 0)
349 || ((SuperBlock->
BlockSize & (sizeof (UINT32) - 1)) != 0)
361 FreePool (SuperBlock);
388 *SuperBlockPtr = SuperBlock;
395 if (SuperBlock != NULL) {
396 FreePool (SuperBlock);
399 return EFI_UNSUPPORTED;
405 OUT UINT32 *DriverSize,
406 OUT VOID **DriverBuffer
416 if (EFI_ERROR (Status)) {
419 "OCJS: Failed to read JumpStart for %g - %r\n",
420 &PrivateData->LocationInfo.ContainerUuid,
433 FreePool (JumpStart);
435 if (EFI_ERROR (Status)) {
438 "OCJS: Failed to read driver for %g - %r\n",
439 &PrivateData->LocationInfo.ContainerUuid,
#define APFS_NX_EFI_JUMPSTART_MAGIC
#define APFS_NX_MINIMUM_BLOCK_SIZE
#define APFS_NX_SIGNATURE
#define APFS_OBJ_EPHEMERAL
#define APFS_NX_MAXIMUM_BLOCK_SIZE
#define APFS_OBJECT_TYPE_NX_SUPERBLOCK
EFI_BLOCK_IO_PROTOCOL * InternalApfsTranslateBlock(IN APFS_PRIVATE_DATA *PrivateData, IN UINT64 Block, OUT EFI_LBA *Lba)
#define APFS_MOD_MAX_UINT32(Value, Result)
STATIC BOOLEAN ApfsBlockChecksumVerify(APFS_OBJ_PHYS *Block, UINTN DataSize)
STATIC EFI_STATUS ApfsReadJumpStart(IN APFS_PRIVATE_DATA *PrivateData, OUT APFS_NX_EFI_JUMPSTART **JumpStartPtr)
EFI_STATUS InternalApfsReadDriver(IN APFS_PRIVATE_DATA *PrivateData, OUT UINT32 *DriverSize, OUT VOID **DriverBuffer)
STATIC EFI_STATUS ApfsReadDriver(IN APFS_PRIVATE_DATA *PrivateData, IN APFS_NX_EFI_JUMPSTART *JumpStart, OUT UINT32 *DriverSize, OUT VOID **DriverBuffer)
EFI_STATUS InternalApfsReadSuperBlock(IN EFI_BLOCK_IO_PROTOCOL *BlockIo, OUT APFS_NX_SUPERBLOCK **SuperBlockPtr)
STATIC UINT64 ApfsFletcher64(VOID *Data, UINTN DataSize)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
APFS_PHYSICAL_RANGE RecordExtents[]
APFS_OBJ_PHYS BlockHeader
APFS_OBJ_PHYS BlockHeader