HDDinfo.inf
## [Defines] INF_VERSION = 0x00010005 BASE_NAME = HDDinfo FILE_GUID = 4aA8A36E-ED34-44db-AE97-1FA5E4ED7776 MODULE_TYPE = UEFI_APPLICATION VERSION_STRING = 1.0 ENTRY_POINT = UefiMain [Sources] HDDinfo.c [Packages] MdePkg/MdePkg.dec ShellPkg/ShellPkg.dec MdeModulePkg/MdeModulePkg.dec [LibraryClasses] UefiBootServicesTableLib UefiLib UefiRuntimeServicesTableLib UefiApplicationEntryPoint PrintLib DebugLib [Protocols] gEfiDiskInfoProtocolGuid
HDDinfo.c
#include <Library/UefiLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/MemoryAllocationLib.h> #include <Library/DebugLib.h> #include <Protocol/DiskInfo.h> #include <Protocol/IdeControllerInit.h> #include <Include/Base.h> #define MODEL_NAME_SIZE 40 #define SECTOR_SIZE 512 #define BYTE_SIZE 8 #define MILLION 1000000 #define KILOBYTE 1024 #define MEGABYTE (1024*1024) #define GIGABYTE (1024*1024*1024) #define TERABYTE (1024*1024*1024*1024) #define MAX_VALUE_48_BIT_ADDRESSING 0x0FFFFFFFFFFFF typedef enum {SATADrive,sSATADrive,SASDrive,OtherDrive} Storage_Drive_Type; typedef struct{ //I didn't implement a function to identify the current port number in this sample. UINT8 PortNumber; //I didn't implement a function to identify the Storage_Drive_Type in this sample. Storage_Drive_Type DriveType; CHAR16 DriveName[40]; UINTN DriveCapacity; //Byte } Storage_Drive_Information; VOID AsciiToUnicode (CHAR8 *AsciiString,CHAR16 *UnicodeString) { UINT8 i; i = 0; while (AsciiString[i] != 0) { UnicodeString[i] = (CHAR16) AsciiString[i]; i++; } UnicodeString[i] = '\0'; } VOID Swap(UINT8* a,UINT8* b) { UINT8 temp; temp = *b; *b = *a; *a = temp; } VOID InitIdentifyDriveInformation(EFI_DISK_INFO_PROTOCOL *DiskInfo,EFI_IDENTIFY_DATA *IdentifyDriveInfo) { UINT32 Size = sizeof (EFI_IDENTIFY_DATA); EFI_STATUS Status; Status = DiskInfo->Identify ( DiskInfo, IdentifyDriveInfo, &Size ); ASSERT_EFI_ERROR(Status); } VOID GetStorageDeviceName(EFI_IDENTIFY_DATA *IdentifyDriveInfo,Storage_Drive_Information* DriveInfo) { UINTN i; for(i = 0;i < sizeof(IdentifyDriveInfo->AtaData.ModelName);i += 2) Swap(&IdentifyDriveInfo->AtaData.ModelName[i],&IdentifyDriveInfo->AtaData.ModelName[i+1]); AsciiToUnicode ((CHAR8 *) &IdentifyDriveInfo->AtaData.ModelName, DriveInfo->DriveName); for(i = 0;i < MODEL_NAME_SIZE; i++) if(DriveInfo->DriveName[i]==0x20 && DriveInfo->DriveName[i+1]==0x20){ DriveInfo->DriveName[i] = '\0'; break; } } UINTN GetStorageDeviceSize(EFI_IDENTIFY_DATA *IdentifyDriveInfo) { UINTN DriveCapacity = 0; UINTN offset; UINTN ShiftCount; //Devices that conform to this standard shall clear bit 15 to zero. if ((IdentifyDriveInfo->AtaData.config & BIT15) == 0) { //48-bit Address feature set is supported if (IdentifyDriveInfo->AtaData.command_set_supported_83 & BIT10) { ShiftCount = sizeof(IdentifyDriveInfo->AtaData.maximum_lba_for_48bit_addressing[0]) * BYTE_SIZE; DriveCapacity = IdentifyDriveInfo->AtaData.maximum_lba_for_48bit_addressing[0]; for (offset = 1; offset < (sizeof(IdentifyDriveInfo->AtaData.maximum_lba_for_48bit_addressing)/ sizeof(IdentifyDriveInfo->AtaData.maximum_lba_for_48bit_addressing[0])); offset++) { DriveCapacity |= (UINTN)IdentifyDriveInfo->AtaData.maximum_lba_for_48bit_addressing[offset] << (ShiftCount * offset); } DriveCapacity = (DriveCapacity&MAX_VALUE_48_BIT_ADDRESSING) * SECTOR_SIZE; } else { ShiftCount = sizeof(IdentifyDriveInfo->AtaData.user_addressable_sectors_hi) * BYTE_SIZE; DriveCapacity =(IdentifyDriveInfo->AtaData.user_addressable_sectors_hi << ShiftCount) | IdentifyDriveInfo->AtaData.user_addressable_sectors_lo * SECTOR_SIZE; } } return DriveCapacity; } EFI_STATUS EFIAPI UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_IDENTIFY_DATA *IdentifyDriveInfo = NULL; UINTN HandleCount; EFI_HANDLE *HandleBuffer; EFI_DISK_INFO_PROTOCOL *DiskInfo; UINTN Index; Storage_Drive_Information *DriveInfo; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiDiskInfoProtocolGuid, NULL, &HandleCount, &HandleBuffer ); ASSERT_EFI_ERROR(Status); DriveInfo = AllocatePool (sizeof(Storage_Drive_Information)*HandleCount); for (Index = 0; Index < HandleCount; Index++) { Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDiskInfoProtocolGuid, &DiskInfo); ASSERT_EFI_ERROR(Status); IdentifyDriveInfo = AllocatePool (sizeof (EFI_IDENTIFY_DATA)); InitIdentifyDriveInformation(DiskInfo,IdentifyDriveInfo); GetStorageDeviceName(IdentifyDriveInfo,&DriveInfo[Index]); DriveInfo[Index].DriveCapacity = GetStorageDeviceSize(IdentifyDriveInfo); gBS->FreePool (IdentifyDriveInfo); } for(Index = 0; Index < HandleCount;Index ++) { Print(L"Drive Model Name: %s , ",DriveInfo[Index].DriveName); Print(L"Drive Size: %d GB\n",DriveInfo[Index].DriveCapacity/GIGABYTE); } gBS->FreePool(DriveInfo); return EFI_SUCCESS; }
Execution Result:
Fig. 1. Result. |
A: Please check the chipset Spec. of your platform and use EFI_DISK_INFO_PROTOCOL (WhichIde() function) as well as EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
Reference:
1. ATA_IDENTIFY_DATA Struct Reference
2. AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
3. UEFI/PI Spec
Hi, I was reading this and it is very informative and useful.
回覆刪除I have one question, as I have not being able get the Port Number for the SATA Drive; How do you get the Port Number?
Hi, It is based on your platform. So you should check the chipsets specification of your platform, and then, you can use the protocol to get the port number.
刪除Hello Wei 大大,
回覆刪除If i want to implement port number, i need what information to decode?
每個平台的讀法不盡相同,得看Spec.才能知道
刪除