/*++ Copyright (c) 1999 Intel Corporation Module Name: EfiDump.c Abstract: Dump out info about EFI structs Revision History --*/ #include "shelle.h" #include "fat.h" typedef union { FAT_BOOT_SECTOR Fat; FAT_BOOT_SECTOR_EX Fat32; } EFI_FAT_BOOT_SECTOR; FAT_VOLUME_TYPE ValidBPB ( IN EFI_FAT_BOOT_SECTOR *Bpb, IN UINTN BlockSize ); VOID DumpBpb ( IN FAT_VOLUME_TYPE FatType, IN EFI_FAT_BOOT_SECTOR *Bpb, IN UINTN BlockSize ); typedef union { VOID *RawData; UINT8 *PtrMath; EFI_TABLE_HEADER *Hdr; EFI_PARTITION_HEADER *Partition; EFI_SYSTEM_TABLE *Sys; EFI_RUNTIME_SERVICES *RT; EFI_BOOT_SERVICES *BS; } EFI_TABLE_HEADER_PTR; VOID EFIFileAttributePrint ( IN UINT64 Attrib ); CHAR16 * EFIClassString ( IN UINT32 Class ); BOOLEAN IsValidEfiHeader ( IN UINTN BlockSize, IN EFI_TABLE_HEADER_PTR Hdr ); VOID EFITableHeaderPrint ( IN VOID *Buffer, IN UINTN ByteSize, IN UINT64 BlockAddress, IN BOOLEAN IsBlkDevice ); VOID DumpGenericHeader ( IN EFI_TABLE_HEADER_PTR Tbl ); VOID DumpPartition ( IN EFI_TABLE_HEADER_PTR Tbl ); VOID DumpFileHeader ( IN EFI_TABLE_HEADER_PTR Tbl ); VOID DumpSystemTable ( IN EFI_TABLE_HEADER_PTR Tbl ); UINT8 FatNumber[] = { 12, 16, 32, 0 }; VOID EFIStructsPrint ( IN VOID *Buffer, IN UINTN BlockSize, IN UINT64 BlockAddress, IN EFI_BLOCK_IO *BlkIo ) { MASTER_BOOT_RECORD *Mbr; INTN i; BOOLEAN IsBlkDevice; FAT_VOLUME_TYPE FatType; Print (L"\n"); Mbr = NULL; if (BlockAddress == 0 && BlkIo != NULL) { Mbr = (MASTER_BOOT_RECORD *)Buffer; if (ValidMBR (Mbr, BlkIo)) { Print (L" Valid MBR\n ---------\n"); for (i=0; iPartition[i].OSIndicator, EXTRACT_UINT32(Mbr->Partition[i].StartingLBA), EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) ); } } else if ((FatType = ValidBPB ((EFI_FAT_BOOT_SECTOR*) Buffer, BlockSize)) != FatUndefined) { DumpBpb (FatType, (EFI_FAT_BOOT_SECTOR*) Buffer, BlockSize); } } if (!Mbr) { IsBlkDevice = (BlkIo != NULL); EFITableHeaderPrint (Buffer, BlockSize, BlockAddress, IsBlkDevice); } } typedef VOID (*EFI_DUMP_HEADER) ( IN EFI_TABLE_HEADER_PTR Tbl ); typedef struct { UINT64 Signature; CHAR16 *String; EFI_DUMP_HEADER Func; } TABLE_HEADER_INFO; TABLE_HEADER_INFO TableHeader[] = { EFI_PARTITION_SIGNATURE, L"Partition", DumpPartition, EFI_SYSTEM_TABLE_SIGNATURE, L"System", DumpSystemTable, EFI_BOOT_SERVICES_SIGNATURE, L"Boot Services", DumpGenericHeader, EFI_RUNTIME_SERVICES_SIGNATURE, L"Runtime Services", DumpGenericHeader, 0x00, L"", DumpGenericHeader }; VOID EFITableHeaderPrint ( IN VOID *Buffer, IN UINTN ByteSize, IN UINT64 BlockAddress, IN BOOLEAN IsBlkDevice ) { EFI_TABLE_HEADER_PTR Hdr; INTN i; Hdr.RawData = Buffer; if (IsValidEfiHeader (ByteSize, Hdr)) { for (i=0; TableHeader[i].Signature != 0x00; i++) { if (TableHeader[i].Signature == Hdr.Hdr->Signature) { Print (L" Valid EFI Header at %a %016lx\n ----------------------------------------%a\n", (IsBlkDevice ? "LBA":"Address"), BlockAddress, (IsBlkDevice ? "":"----") ); Print (L" %H%s: Table Structure%N size %08x revision %08x\n", TableHeader[i].String, Hdr.Hdr->HeaderSize, Hdr.Hdr->Revision); TableHeader[i].Func (Hdr); return; } } /* * Dump the Generic Header, since we don't know the type */ TableHeader[i].Func (Hdr); } } BOOLEAN IsValidEfiHeader ( IN UINTN BlockSize, IN EFI_TABLE_HEADER_PTR Hdr ) { if (Hdr.Hdr->HeaderSize == 0x00) { return FALSE; } if (Hdr.Hdr->HeaderSize > BlockSize) { return FALSE; } return TRUE; } VOID DumpGenericHeader ( IN EFI_TABLE_HEADER_PTR Tbl ) { Print (L" Header 0x%016lx Revision 0x%08x Size 0x%08x CRC 0x%08x\n", Tbl.Hdr->Signature, Tbl.Hdr->Revision, Tbl.Hdr->HeaderSize, Tbl.Hdr->CRC32 ); } VOID DumpPartition ( IN EFI_TABLE_HEADER_PTR Tbl ) { Print (L" LBA's 0x%016lx - 0x%016lx Unusable (0x%016lx)\n", Tbl.Partition->FirstUsableLba, Tbl.Partition->LastUsableLba, Tbl.Partition->UnusableSpace ); Print (L" Free Space LBA 0x%016lx Root LBA 0x%016lx\n", Tbl.Partition->FreeSpace, Tbl.Partition->RootFile ); Print (L" Block Size 0x%08x Dir Allocation Units 0x%08x\n", Tbl.Partition->BlockSize, Tbl.Partition->DirectoryAllocationNumber ); } CHAR16 * EFIClassString ( IN UINT32 Class ) { switch (Class) { case EFI_FILE_CLASS_FREE_SPACE: return L"Free Space"; case EFI_FILE_CLASS_EMPTY: return L"Empty"; case EFI_FILE_CLASS_NORMAL: return L"Nornal"; default: return L"Invalid"; } } VOID DumpSystemTable ( IN EFI_TABLE_HEADER_PTR Tbl ) { EFI_STATUS Status; EFI_DEVICE_PATH *DevicePath; VOID *AcpiTable = NULL; VOID *SMBIOSTable = NULL; VOID *SalSystemTable = NULL; VOID *MpsTable = NULL; Print (L" ConIn (0x%08x) ConOut (0x%08x) StdErr (0x%08x)\n", Tbl.Sys->ConsoleInHandle, Tbl.Sys->ConsoleOutHandle, Tbl.Sys->StandardErrorHandle ); Status = BS->HandleProtocol (Tbl.Sys->ConsoleInHandle, &DevicePathProtocol, (VOID*)&DevicePath); if (Status == EFI_SUCCESS && DevicePath) { Print (L" Console In on %s\n", DevicePathToStr (DevicePath)); } Status = BS->HandleProtocol (Tbl.Sys->ConsoleOutHandle, &DevicePathProtocol, (VOID*)&DevicePath); if (Status == EFI_SUCCESS && DevicePath) { Print (L" Console Out on %s\n", DevicePathToStr (DevicePath)); } Status = BS->HandleProtocol (Tbl.Sys->StandardErrorHandle, &DevicePathProtocol, (VOID*)&DevicePath); if (Status == EFI_SUCCESS && DevicePath) { Print (L" Std Error on %s\n", DevicePathToStr (DevicePath)); } Print (L" Runtime Services 0x%016lx\n", (UINT64)Tbl.Sys->RuntimeServices); Print (L" Boot Services 0x%016lx\n", (UINT64)Tbl.Sys->BootServices); Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, &SalSystemTable); if (!EFI_ERROR(Status)) { Print (L" SAL System Table 0x%016lx\n", (UINT64)SalSystemTable); } Status = LibGetSystemConfigurationTable(&AcpiTableGuid, &AcpiTable); if (!EFI_ERROR(Status)) { Print (L" ACPI Table 0x%016lx\n", (UINT64)AcpiTable); } Status = LibGetSystemConfigurationTable(&MpsTableGuid, &MpsTable); if (!EFI_ERROR(Status)) { Print (L" MPS Table 0x%016lx\n", (UINT64)MpsTable); } Status = LibGetSystemConfigurationTable(&SMBIOSTableGuid, &SMBIOSTable); if (!EFI_ERROR(Status)) { Print (L" SMBIOS Table 0x%016lx\n", (UINT64)SMBIOSTable); } } FAT_VOLUME_TYPE ValidBPB ( IN EFI_FAT_BOOT_SECTOR *Bpb, IN UINTN BlockSize ) { UINT32 BlockSize32; BOOLEAN IsFat; UINT32 RootSize; UINT32 RootLba; UINT32 FirstClusterLba; UINT32 MaxCluster; UINT32 Sectors; FAT_VOLUME_TYPE FatType; BlockSize32 = (UINT32)BlockSize; if (Bpb->Fat.SectorsPerFat == 0) { FatType = FAT32; } else { FatType = FatUndefined; } IsFat = TRUE; if (Bpb->Fat.Ia32Jump[0] != 0xe9 && Bpb->Fat.Ia32Jump[0] != 0xeb && Bpb->Fat.Ia32Jump[0] != 0x49) { IsFat = FALSE; } Sectors = (Bpb->Fat.Sectors == 0) ? Bpb->Fat.LargeSectors : Bpb->Fat.Sectors; if (Bpb->Fat.SectorSize != BlockSize32 || Bpb->Fat.ReservedSectors == 0 || Bpb->Fat.NoFats == 0 || Sectors == 0 ) { IsFat = FALSE; } if (Bpb->Fat.SectorsPerCluster != 1 && Bpb->Fat.SectorsPerCluster != 2 && Bpb->Fat.SectorsPerCluster != 4 && Bpb->Fat.SectorsPerCluster != 8 && Bpb->Fat.SectorsPerCluster != 16 && Bpb->Fat.SectorsPerCluster != 32 && Bpb->Fat.SectorsPerCluster != 64 && Bpb->Fat.SectorsPerCluster != 128) { IsFat = FALSE; } if (FatType == FAT32 && (Bpb->Fat32.LargeSectorsPerFat == 0 || Bpb->Fat32.FsVersion != 0)) { IsFat = FALSE; } if (Bpb->Fat.Media != 0xf0 && Bpb->Fat.Media != 0xf8 && Bpb->Fat.Media != 0xf9 && Bpb->Fat.Media != 0xfb && Bpb->Fat.Media != 0xfc && Bpb->Fat.Media != 0xfd && Bpb->Fat.Media != 0xfe && Bpb->Fat.Media != 0xff && /* FujitsuFMR */ Bpb->Fat.Media != 0x00 && Bpb->Fat.Media != 0x01 && Bpb->Fat.Media != 0xfa) { IsFat = FALSE; } if (FatType != FAT32 && Bpb->Fat.RootEntries == 0) { IsFat = FALSE; } /* If this is fat32, refuse to mount mirror-disabled volumes */ if (FatType == FAT32 && (Bpb->Fat32.ExtendedFlags & 0x80)) { IsFat = FALSE; } if (FatType != FAT32) { RootSize = Bpb->Fat.RootEntries * sizeof(FAT_DIRECTORY_ENTRY); RootLba = Bpb->Fat.NoFats * Bpb->Fat.SectorsPerFat + Bpb->Fat.ReservedSectors; FirstClusterLba = RootLba + (RootSize / Bpb->Fat.SectorSize); MaxCluster = (Bpb->Fat.Sectors - FirstClusterLba) / Bpb->Fat.SectorsPerCluster; FatType = (MaxCluster + 1) < 4087 ? FAT12 : FAT16; } return (IsFat ? FatType : FatUndefined); } VOID DumpBpb ( IN FAT_VOLUME_TYPE FatType, IN EFI_FAT_BOOT_SECTOR *Bpb, IN UINTN BlockSize ) { UINT32 Sectors; Sectors = (Bpb->Fat.Sectors == 0) ? Bpb->Fat.LargeSectors : Bpb->Fat.Sectors; Print (L"%HFat %d%N BPB ", FatNumber[FatType]); if (FatType == FAT32) { Print (L"FatLabel: '%.*a' SystemId: '%.*a' OemId: '%.*a'\n", sizeof(Bpb->Fat32.FatLabel), Bpb->Fat32.FatLabel, sizeof(Bpb->Fat32.SystemId), Bpb->Fat32.SystemId, sizeof(Bpb->Fat32.OemId), Bpb->Fat32.OemId ); } else { Print (L"FatLabel: '%.*a' SystemId: '%.*a' OemId: '%.*a'\n", sizeof(Bpb->Fat.FatLabel), Bpb->Fat.FatLabel, sizeof(Bpb->Fat.SystemId), Bpb->Fat.SystemId, sizeof(Bpb->Fat.OemId), Bpb->Fat.OemId ); } Print (L" SectorSize 0x%x SectorsPerCluster %d", Bpb->Fat.SectorSize, Bpb->Fat.SectorsPerCluster); Print (L" ReservedSectors %d # Fats %d\n Root Entries 0x%x Media 0x%x", Bpb->Fat.ReservedSectors, Bpb->Fat.NoFats, Bpb->Fat.RootEntries, Bpb->Fat.Media); if (FatType == FAT32) { Print (L" Sectors 0x%x SectorsPerFat 0x%x\n", Sectors, Bpb->Fat32.LargeSectorsPerFat); } else { Print (L" Sectors 0x%x SectorsPerFat 0x%x\n", Sectors, Bpb->Fat.SectorsPerFat); } Print (L" SectorsPerTrack 0x%x Heads %d\n", Bpb->Fat.SectorsPerTrack, Bpb->Fat.Heads); }