/** Check if it's a valid FFS file. Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. @param ErasePolarity Erase polarity attribute of the firmware volume @param FfsHeader Points to the FFS file to be checked @retval TRUE Valid FFS file @retval FALSE Invalid FFS file **/ BOOLEAN IsValidFfsFile ( IN UINT8 ErasePolarity, IN EFI_FFS_FILE_HEADER *FfsHeader ) { EFI_FFS_FILE_STATE FileState; UINT8 DataCheckSum; FileState = GetFileState (ErasePolarity, FfsHeader); switch (FileState) { case EFI_FILE_DELETED: case EFI_FILE_DATA_VALID: case EFI_FILE_MARKED_FOR_UPDATE: DataCheckSum = FFS_FIXED_CHECKSUM; if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) == FFS_ATTRIB_CHECKSUM) { if (IS_FFS_FILE2 (FfsHeader)) { DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (FfsHeader) - sizeof(EFI_FFS_FILE_HEADER2)); } else { DataCheckSum = CalculateCheckSum8 ((CONST UINT8 *) FfsHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (FfsHeader) - sizeof(EFI_FFS_FILE_HEADER)); } } if (FfsHeader->IntegrityCheck.Checksum.File == DataCheckSum) { return TRUE; } default: return FALSE; } }
/** Calculate the checksum for a PAD file. @param PadFileHeader The Pad File to be caculeted the checksum. **/ VOID SetPadFileChecksum ( IN EFI_FFS_FILE_HEADER *PadFileHeader ) { if ((PadFileHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) { if (IS_FFS_FILE2 (PadFileHeader)) { // // Calculate checksum of Pad File Data // PadFileHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER2), FFS_FILE2_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER2)); } else { // // Calculate checksum of Pad File Data // PadFileHeader->IntegrityCheck.Checksum.File = CalculateCheckSum8 ((UINT8 *) PadFileHeader + sizeof (EFI_FFS_FILE_HEADER), FFS_FILE_SIZE (PadFileHeader) - sizeof (EFI_FFS_FILE_HEADER)); } } else { PadFileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; } return ; }
/** Install TCG ACPI Table when ACPI Table Protocol is available. A system's firmware uses an ACPI table to identify the system's TCG capabilities to the Post-Boot environment. The information in this ACPI table is not guaranteed to be valid until the Host Platform transitions from pre-boot state to post-boot state. @param[in] Event Event whose notification function is being invoked @param[in] Context Pointer to the notification function's context **/ VOID EFIAPI InstallAcpiTable ( IN EFI_EVENT Event, IN VOID* Context ) { UINTN TableKey; EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; UINT8 Checksum; Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable); if (EFI_ERROR (Status)) { return; } if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) { // // The ACPI table must be checksumed before calling the InstallAcpiTable() // service of the ACPI table protocol to install it. // Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate)); mTcgClientAcpiTemplate.Header.Checksum = Checksum; Status = AcpiTable->InstallAcpiTable ( AcpiTable, &mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate), &TableKey ); } else { // // The ACPI table must be checksumed before calling the InstallAcpiTable() // service of the ACPI table protocol to install it. // Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate)); mTcgServerAcpiTemplate.Header.Checksum = Checksum; Status = AcpiTable->InstallAcpiTable ( AcpiTable, &mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate), &TableKey ); } ASSERT_EFI_ERROR (Status); }
/** This function calculates and updates an UINT8 checksum. @param Buffer Pointer to buffer to checksum @param Size Number of bytes to checksum **/ VOID AcpiPlatformChecksum ( IN UINT8 *Buffer, IN UINTN Size ) { UINTN ChecksumOffset; ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum); // // Set checksum to 0 first // Buffer[ChecksumOffset] = 0; // // Update checksum value // Buffer[ChecksumOffset] = CalculateCheckSum8(Buffer, Size); }
VOID *FindSignature(VOID* Start, UINT32 Signature, BOOLEAN NoChecksum) { UINT8 *Ptr = (UINT8*)Start; UINT32 Count = 0x10000; // 16 pages while (Count-- > 0) { if ( *(UINT32*)Ptr == Signature && ((EFI_ACPI_DESCRIPTION_HEADER *)Ptr)->Length <= Count && (NoChecksum || CalculateCheckSum8(Ptr, ((EFI_ACPI_DESCRIPTION_HEADER *)Ptr)->Length) == 0 )) { return Ptr; } Ptr++; } return NULL; }
VOID ErstSetAcpiTable ( ERST_BOOT_CONTEXT *Context ) { UINTN AcpiTableHandle; EFI_STATUS Status; UINT8 Checksum; mErst.ErstTableHeader.Header.Length = sizeof (ERST_TABLE); Checksum = CalculateCheckSum8 ((UINT8*)(&mErst), mErst.ErstTableHeader.Header.Length); mErst.ErstTableHeader.Header.Checksum = Checksum; AcpiTableHandle = 0; Status = mAcpiTableProtocol->InstallAcpiTable ( mAcpiTableProtocol, &mErst, mErst.ErstTableHeader.Header.Length, &AcpiTableHandle ); ASSERT_EFI_ERROR (Status) ; }
/** Process a QEMU_LOADER_ADD_CHECKSUM command. @param[in] AddChecksum The QEMU_LOADER_ADD_CHECKSUM command to process. @param[in] Tracker The ORDERED_COLLECTION tracking the BLOB user structures created thus far. @retval EFI_PROTOCOL_ERROR Malformed fw_cfg file name has been found in AddChecksum, or the AddChecksum command references a file unknown to Tracker, or the range to checksum is invalid. @retval EFI_SUCCESS The requested range has been checksummed. **/ STATIC EFI_STATUS EFIAPI ProcessCmdAddChecksum ( IN CONST QEMU_LOADER_ADD_CHECKSUM *AddChecksum, IN CONST ORDERED_COLLECTION *Tracker ) { ORDERED_COLLECTION_ENTRY *TrackerEntry; BLOB *Blob; if (AddChecksum->File[QEMU_LOADER_FNAME_SIZE - 1] != '\0') { DEBUG ((EFI_D_ERROR, "%a: malformed file name\n", __FUNCTION__)); return EFI_PROTOCOL_ERROR; } TrackerEntry = OrderedCollectionFind (Tracker, AddChecksum->File); if (TrackerEntry == NULL) { DEBUG ((EFI_D_ERROR, "%a: invalid blob reference \"%a\"\n", __FUNCTION__, AddChecksum->File)); return EFI_PROTOCOL_ERROR; } Blob = OrderedCollectionUserStruct (TrackerEntry); if (Blob->Size <= AddChecksum->ResultOffset || Blob->Size < AddChecksum->Length || Blob->Size - AddChecksum->Length < AddChecksum->Start) { DEBUG ((EFI_D_ERROR, "%a: invalid checksum range in \"%a\"\n", __FUNCTION__, AddChecksum->File)); return EFI_PROTOCOL_ERROR; } Blob->Base[AddChecksum->ResultOffset] = CalculateCheckSum8 ( Blob->Base + AddChecksum->Start, AddChecksum->Length ); DEBUG ((EFI_D_VERBOSE, "%a: File=\"%a\" ResultOffset=0x%x Start=0x%x " "Length=0x%x\n", __FUNCTION__, AddChecksum->File, AddChecksum->ResultOffset, AddChecksum->Start, AddChecksum->Length)); return EFI_SUCCESS; }
VOID BertSetAcpiTable ( IN BERT_CONTEXT *Context ) { UINTN AcpiTableHandle; EFI_STATUS Status; if (Context == NULL) { return; } EFI_ACPI_6_0_BOOT_ERROR_RECORD_TABLE_HEADER* Bert = Context->BertHeader; Bert->Header.Checksum = CalculateCheckSum8 ((UINT8*)(Bert), Bert->Header.Length); AcpiTableHandle = 0; Status = mAcpiTableProtocol->InstallAcpiTable ( mAcpiTableProtocol, Bert, Bert->Header.Length, &AcpiTableHandle); ASSERT_EFI_ERROR (Status); return; }
/** Install TCG ACPI Table when ACPI Table Protocol is available. A system's firmware uses an ACPI table to identify the system's TCG capabilities to the Post-Boot environment. The information in this ACPI table is not guaranteed to be valid until the Host Platform transitions from pre-boot state to post-boot state. @param[in] Event Event whose notification function is being invoked @param[in] Context Pointer to the notification function's context **/ VOID EFIAPI InstallAcpiTable ( IN EFI_EVENT Event, IN VOID* Context ) { UINTN TableKey; EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; UINT8 Checksum; UINT64 OemTableId; Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTable); if (EFI_ERROR (Status)) { return; } if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_CLIENT) { CopyMem (mTcgClientAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgClientAcpiTemplate.Header.OemId)); OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); CopyMem (&mTcgClientAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64)); mTcgClientAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); mTcgClientAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); mTcgClientAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); // // The ACPI table must be checksumed before calling the InstallAcpiTable() // service of the ACPI table protocol to install it. // Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate)); mTcgClientAcpiTemplate.Header.Checksum = Checksum; Status = AcpiTable->InstallAcpiTable ( AcpiTable, &mTcgClientAcpiTemplate, sizeof (mTcgClientAcpiTemplate), &TableKey ); } else { CopyMem (mTcgServerAcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTcgServerAcpiTemplate.Header.OemId)); OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); CopyMem (&mTcgServerAcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64)); mTcgServerAcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); mTcgServerAcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); mTcgServerAcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); // // The ACPI table must be checksumed before calling the InstallAcpiTable() // service of the ACPI table protocol to install it. // Checksum = CalculateCheckSum8 ((UINT8 *)&mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate)); mTcgServerAcpiTemplate.Header.Checksum = Checksum; mTcgServerAcpiTemplate.BaseAddress.Address = PcdGet64 (PcdTpmBaseAddress); Status = AcpiTable->InstallAcpiTable ( AcpiTable, &mTcgServerAcpiTemplate, sizeof (mTcgServerAcpiTemplate), &TableKey ); } if (EFI_ERROR (Status)) { DEBUG((EFI_D_ERROR, "Tcg Acpi Table installation failure")); } }
/** This function set TXT HEAP. @param MleLoadAddress MLE address @param MleLoadSize MLE size @param PageTableBase page table base **/ VOID TxtSetupHeap ( IN UINT64 MleLoadAddress, IN UINT64 MleLoadSize, IN UINT64 PageTableBase ) { VOID *TxtOsMleData; MLE_PRIVATE_DATA *MlePrivateData; DCE_PRIVATE_DATA *DcePrivateData; TXT_OS_TO_SINIT_DATA *OsSinitData; TXT_SINIT_TO_MLE_DATA *SinitMleData; TXT_ACM_FORMAT *SinitAcm; TXT_CHIPSET_ACM_INFORMATION_TABLE *ChipsetAcmInformationTable; UINTN TxtHeapSize; UINTN TxtHeapOccupiedSize; // // MlePrivateData // TxtOsMleData = GetTxtOsToMleData(); DEBUG((EFI_D_INFO, "(TXT) TxtOsMleData - 0x%x\n", TxtOsMleData)); *((UINT64 *)TxtOsMleData - 1) = sizeof(UINT64) + sizeof(TXT_OS_TO_MLE_DATA_STRUCT); MlePrivateData = GetMlePrivateData (); DcePrivateData = &MlePrivateData->DcePrivateData; AsmReadGdtr (&MlePrivateData->Gdtr); AsmReadIdtr (&MlePrivateData->Idtr); MlePrivateData->Ds = AsmReadDs (); MlePrivateData->TempEsp = (UINT32)(UINT32)((UINTN)GetTxtHeap () + GetTxtHeapSize () - MLE_TEMP_STACK_SIZE_RLP - 0x20); // // Patch CS/Offset in stack // // +---------+ // | Offset | // +---------+ // | CS | // +---------+ // | Dummy | // +---------+ // | Dummy | // +---------+ // | Dummy | // +---------+ // | Dummy | // +---------+ <- TempEsp if (PostInitAddr != 0) { MlePrivateData->PostSinitOffset = (UINT32)((UINTN)AsmMleEntryPoint + PostInitAddr); MlePrivateData->PostSinitSegment = (UINT32)AsmReadCs(); } MlePrivateData->Lock = 0; MlePrivateData->RlpInitializedNumber = 0; // // OsSinitData // OsSinitData = GetTxtOsToSinitData (); DEBUG((EFI_D_INFO, "(TXT) OsSinitData - 0x%x\n", OsSinitData)); *((UINT64 *)OsSinitData - 1) = sizeof(UINT64) + sizeof(*OsSinitData); OsSinitData->Version = TXT_OS_TO_SINIT_DATA_VERSION; OsSinitData->Flags = 0; OsSinitData->MLEPageTableBase = PageTableBase; // // We copy MleHeader to DPR // { TXT_MLE_HEADER *MleHeader; MleHeader = (TXT_MLE_HEADER *)(UINTN)MleLoadAddress; CopyMem (&MleHeader->Uuid, &gMleHeaderUuid, sizeof(gMleHeaderUuid)); MleHeader->HeaderLen = sizeof(*MleHeader); MleHeader->Version = TXT_MLE_HEADER_VERSION; MleHeader->EntryPoint = (UINT32)(UINTN)MleHeader + sizeof(*MleHeader); if (MleHeader->Version < TXT_MLE_HEADER_VERSION_2_1) { MleHeader->EntryPoint -= (sizeof(MleHeader->CmdlineStart) + sizeof(MleHeader->CmdlineEnd)); } // // Patch the instruction for ILP // *(UINT8 *)(UINTN)MleHeader->EntryPoint = 0x90; // nop *(UINT8 *)((UINTN)MleHeader->EntryPoint + 1) = 0xE9; // near jmp *(UINT32 *)((UINTN)MleHeader->EntryPoint + 2) = (UINT32)((UINTN)AsmMleEntryPoint - ((UINTN)MleHeader->EntryPoint + 6)); // minus next instruction // // Patch the instrution for RLPs: cli, hlt, and jmp $-2 // *(UINT32 *)((UINTN)MleHeader->EntryPoint + 6) = 0xFCEBF4FA; MleHeader->EntryPoint -= (UINT32)PageTableBase; if (MleHeader->Version >= TXT_MLE_HEADER_VERSION_1_1) { MleHeader->FirstValidPage = (UINT32)MleLoadAddress; MleHeader->FirstValidPage -= (UINT32)PageTableBase; MleHeader->MleStart = MleHeader->FirstValidPage; //MleHeader->MleEnd = MleHeader->MleStart + sizeof(*MleHeader) + 10; // Offset (1 nop + 5 jmp + 4 deadloop) MleHeader->MleEnd = MleHeader->MleStart + (UINT32)MleLoadSize; } if (MleHeader->Version >= TXT_MLE_HEADER_VERSION_2) { MleHeader->Capabilities = TXT_MLE_SINIT_CAPABILITY_GETSET_WAKEUP | TXT_MLE_SINIT_CAPABILITY_MONITOR_ADDRESS_RLP_WAKEUP; MleHeader->Capabilities |= TXT_MLE_SINIT_CAPABILITY_ECX_HAS_PAGE_TABLE; #ifdef STM_SUPPORT MleHeader->Capabilities |= TXT_MLE_SINIT_CAPABILITY_STM; #endif } if (MleHeader->Version >= TXT_MLE_HEADER_VERSION_2_1) { MleHeader->CmdlineStart = 0; // Not use MleHeader->CmdlineEnd = 0; // Not use } // // Done // OsSinitData->MLEHeaderBase = (UINT64)(UINTN)MleHeader; OsSinitData->MLEHeaderBase -= PageTableBase; OsSinitData->MLESize = (UINT64)(MleHeader->MleEnd - MleHeader->MleStart); } OsSinitData->PMRLowBase = MlePrivateData->DcePrivateData.PmrLowBase; OsSinitData->PMRLowSize = MlePrivateData->DcePrivateData.PmrLowSize; OsSinitData->PMRHighBase = MlePrivateData->DcePrivateData.PmrHighBase; OsSinitData->PMRHighSize = MlePrivateData->DcePrivateData.PmrHighSize; OsSinitData->LCPPOBase = MlePrivateData->DcePrivateData.LcpPoBase; OsSinitData->LCPPOSize = MlePrivateData->DcePrivateData.LcpPoSize; SinitAcm = (TXT_ACM_FORMAT *)(UINTN)TxtPubRead32 (TXT_SINIT_BASE); ChipsetAcmInformationTable = (TXT_CHIPSET_ACM_INFORMATION_TABLE *) \ ((UINTN)(SinitAcm + 1) + SinitAcm->KeySize * 4 + sizeof(UINT32) + ACM_PKCS_1_5_RSA_SIGNATURE_SIZE + SinitAcm->ScratchSize * 4 ); if ((ChipsetAcmInformationTable->Capabilities & TXT_MLE_SINIT_CAPABILITY_MONITOR_ADDRESS_RLP_WAKEUP) != 0) { OsSinitData->Capabilities = TXT_MLE_SINIT_CAPABILITY_MONITOR_ADDRESS_RLP_WAKEUP; } else { OsSinitData->Capabilities = TXT_MLE_SINIT_CAPABILITY_GETSET_WAKEUP; } OsSinitData->Version = ChipsetAcmInformationTable->OsSinitTableVer; if (ChipsetAcmInformationTable->OsSinitTableVer >= TXT_OS_TO_SINIT_DATA_VERSION_5) { OsSinitData->RsdpPtr = (UINT64)(UINTN)FindAcpiRsdPtr (); if (OsSinitData->RsdpPtr == 0) { OsSinitData->RsdpPtr = (UINT64)(UINTN)&MlePrivateData->UefiRsdp; } if (ChipsetAcmInformationTable->OsSinitTableVer >= TXT_OS_TO_SINIT_DATA_VERSION_6) { if (ChipsetAcmInformationTable->OsSinitTableVer >= TXT_OS_TO_SINIT_DATA_VERSION_7) { OsSinitData->Flags = TXT_OS_TO_SINIT_DATA_FLAGS_MAX_AGILE_POLICY; } // // Fill Event Log data there // TXT_HEAP_EXT_DATA_ELEMENT *Element; TXT_HEAP_EVENTLOG_EXT_ELEMENT *EventLogElement; TXT_EVENT_LOG_CONTAINER *EventLog; TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2 *EventLogPointerElement2; TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2_1 *EventLogPointerElement2_1; TXT_HEAP_EVENT_LOG_DESCR *EventLogDesc; UINTN Index; TCG_LOG_DESCRIPTOR *TcgLogDesc; TCG_PCR_EVENT_HDR *PcrEvent; *((UINT64 *)OsSinitData - 1) = sizeof(UINT64) + sizeof(*OsSinitData); Element = (TXT_HEAP_EXT_DATA_ELEMENT *)(OsSinitData + 1); if (DcePrivateData->TpmType == FRM_TPM_TYPE_TPM12) { // TPM1.2 Element->Type = TXT_HEAP_EXTDATA_TYPE_EVENTLOG_PTR; Element->Size = sizeof(TXT_HEAP_EXT_DATA_ELEMENT) + sizeof(TXT_HEAP_EVENTLOG_EXT_ELEMENT); EventLogElement = (TXT_HEAP_EVENTLOG_EXT_ELEMENT *)(Element + 1); DcePrivateData->EventLogElement = EventLogElement; // // Init EventLogContainer // EventLog = (TXT_EVENT_LOG_CONTAINER *)(UINTN)(MlePrivateData->DcePrivateData.EventLogBase); ZeroMem(EventLog, MAX_EVENT_LOG_BUFFER_SIZE); CopyMem(EventLog->Signature, TXT_EVENTLOG_SIGNATURE, sizeof(TXT_EVENTLOG_SIGNATURE)); EventLog->ContainerVersionMajor = TXT_EVENTLOG_CONTAINER_MAJOR_VERSION; EventLog->ContainerVersionMinor = TXT_EVENTLOG_CONTAINER_MINOR_VERSION; EventLog->PcrEventVersionMajor = TXT_EVENTLOG_EVENT_MAJOR_VERSION; EventLog->PcrEventVersionMinor = TXT_EVENTLOG_EVENT_MINOR_VERSION; EventLog->Size = MAX_EVENT_LOG_BUFFER_SIZE; EventLog->PcrEventsOffset = sizeof(*EventLog); EventLog->NextEventOffset = sizeof(*EventLog); EventLogElement->EventLogAddress = (UINT64)(UINTN)EventLog; *((UINT64 *)OsSinitData - 1) += Element->Size; Element = (TXT_HEAP_EXT_DATA_ELEMENT *)((UINTN)Element + Element->Size); } if (DcePrivateData->TpmType == FRM_TPM_TYPE_TPM2) { // TPM2.0 UINT16 TpmHashAlgo[] = { TPM_ALG_SHA1, TPM_ALG_SHA256, TPM_ALG_SHA384, TPM_ALG_SHA512, TPM_ALG_SM3_256 }; UINTN SubIndex; DcePrivateData->EventHashAlgoIDCount = 0; for (Index = 0; Index < sizeof(TpmHashAlgo) / sizeof(TpmHashAlgo[0]); Index++) { if ((DcePrivateData->ActivePcrBanks & (1 << Index)) != 0) { for (SubIndex = 0; SubIndex < DcePrivateData->AcmTpmHashAlgoIDCount; SubIndex++) { if (DcePrivateData->AcmTpmHashAlgoID[SubIndex] == TpmHashAlgo[Index]) { // Both TPM and ACM support this hash algo. DcePrivateData->EventHashAlgoID[DcePrivateData->EventHashAlgoIDCount] = TpmHashAlgo[Index]; DcePrivateData->EventHashAlgoIDCount++; } } } } if ((DcePrivateData->AcmCapabilities & TXT_MLE_SINIT_CAPABILITY_TCG2_COMPATIBILE_EVENTLOG) == 0) { Element->Type = TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2; EventLogPointerElement2 = (TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2 *)(Element + 1); DcePrivateData->EventLogPointerElement2 = EventLogPointerElement2; EventLogPointerElement2->Count = DcePrivateData->EventHashAlgoIDCount; EventLogDesc = (TXT_HEAP_EVENT_LOG_DESCR *)(EventLogPointerElement2 + 1); Element->Size = sizeof(TXT_HEAP_EXT_DATA_ELEMENT) + sizeof(TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2) + EventLogPointerElement2->Count * sizeof(TXT_HEAP_EVENT_LOG_DESCR); for (Index = 0; Index < EventLogPointerElement2->Count; Index++, EventLogDesc++) { EventLogDesc->HashAlgID = DcePrivateData->EventHashAlgoID[Index]; EventLogDesc->Reserved = 0; EventLogDesc->PhysicalAddress = (UINT64)(UINTN)(MlePrivateData->DcePrivateData.EventLogBase + MAX_EVENT_LOG_BUFFER_SIZE * (Index + 1)); ZeroMem((VOID *)(UINTN)EventLogDesc->PhysicalAddress, MAX_EVENT_LOG_BUFFER_SIZE); EventLogDesc->AllocatedEventContainerSize = MAX_EVENT_LOG_BUFFER_SIZE; if (EventLogDesc->HashAlgID == TPM_ALG_SHA) { PcrEvent = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogDesc->PhysicalAddress; TcgLogDesc = (TCG_LOG_DESCRIPTOR *)(PcrEvent + 1); PcrEvent->PCRIndex = 0; PcrEvent->EventType = EV_NO_ACTION; ZeroMem(&PcrEvent->Digest, sizeof(PcrEvent->Digest)); PcrEvent->EventSize = sizeof(TCG_LOG_DESCRIPTOR); CopyMem(TcgLogDesc->Signature, TCG_LOG_DESCRIPTOR_SIGNATURE, sizeof(TCG_LOG_DESCRIPTOR_SIGNATURE)); TcgLogDesc->Revision = TCG_LOG_DESCRIPTOR_REVISION; TcgLogDesc->DigestAlgID = DIGEST_ALG_ID_SHA_1; TcgLogDesc->DigestSize = SHA1_DIGEST_SIZE; EventLogDesc->FirstRecordOffset = sizeof(TCG_PCR_EVENT_HDR) + PcrEvent->EventSize; EventLogDesc->NextRecordOffset = sizeof(TCG_PCR_EVENT_HDR) + PcrEvent->EventSize; } else { EventLogDesc->FirstRecordOffset = 0; EventLogDesc->NextRecordOffset = 0; } } } else { Element->Type = TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1; EventLogPointerElement2_1 = (TXT_HEAP_EVENT_LOG_POINTER_ELEMENT2_1 *)(Element + 1); DcePrivateData->EventLogPointerElement2_1 = EventLogPointerElement2_1; EventLogPointerElement2_1->PhysicalAddress = (UINT64)(UINTN)(MlePrivateData->DcePrivateData.EventLogBase + MAX_EVENT_LOG_BUFFER_SIZE); ZeroMem((VOID *)(UINTN)EventLogPointerElement2_1->PhysicalAddress, MAX_EVENT_LOG_BUFFER_SIZE); EventLogPointerElement2_1->AllocatedEventContainerSize = MAX_EVENT_LOG_BUFFER_SIZE * 5; EventLogPointerElement2_1->FirstRecordOffset = 0; EventLogPointerElement2_1->NextRecordOffset = 0; } *((UINT64 *)OsSinitData - 1) += Element->Size; Element = (TXT_HEAP_EXT_DATA_ELEMENT *)((UINTN)Element + Element->Size); } Element->Type = TXT_HEAP_EXTDATA_TYPE_END; Element->Size = sizeof(TXT_HEAP_END_ELEMENT); *((UINT64 *)OsSinitData - 1) += sizeof(TXT_HEAP_END_ELEMENT); } } else { // Version 4 *((UINT64 *)OsSinitData - 1) = sizeof(UINT64) + sizeof(*OsSinitData) - sizeof(UINT64); } // // SinitMleData // SinitMleData = GetTxtSinitToMleData (); DEBUG((EFI_D_INFO, "(TXT) SinitMleData - 0x%x\n", SinitMleData)); *((UINT64 *)SinitMleData - 1) = 0; ZeroMem (SinitMleData, sizeof(*SinitMleData)); TxtHeapSize = GetTxtHeapSize (); TxtHeapOccupiedSize = GetTxtHeapOccupiedSize (); DEBUG ((EFI_D_INFO, "(TXT) TXT Heap base - %08x\n", GetTxtHeap ())); DEBUG ((EFI_D_INFO, "(TXT) TXT Heap size - %08x\n", TxtHeapSize)); DEBUG ((EFI_D_INFO, "(TXT) TXT BiosOsData - %08x\n", GetTxtBiosToOsData())); DEBUG ((EFI_D_INFO, "(TXT) TXT OsMleData - %08x\n", (UINTN)TxtOsMleData)); DEBUG ((EFI_D_INFO, "(TXT) TXT OsSinitData - %08x\n", (UINTN)OsSinitData)); DEBUG ((EFI_D_INFO, "(TXT) TXT SinitMleData - %08x\n", (UINTN)SinitMleData)); DEBUG ((EFI_D_INFO, "(TXT) TXT OccupiedSize - %08x\n", TxtHeapOccupiedSize)); // // Check heap // if (TxtHeapOccupiedSize >= TxtHeapSize) { DEBUG ((EFI_D_ERROR, "(TXT) ERROR: TXT Heap overflow - Occupied (%08x), Allocated (%08x)\n", TxtHeapOccupiedSize, TxtHeapSize)); ASSERT(FALSE); } if (OsSinitData->RsdpPtr != 0) { EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; EFI_ACPI_DESCRIPTION_HEADER *Rsdt; EFI_ACPI_DESCRIPTION_HEADER *Xsdt; // validate ACPI RSDP/RSDT/XSDT Rsdp = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)OsSinitData->RsdpPtr; DEBUG ((EFI_D_INFO, "(TXT) RSDP Address - %08x\n", Rsdp)); DEBUG ((EFI_D_INFO, "(TXT) RSDP Checksum - %02x\n", CalculateCheckSum8((UINT8 *)Rsdp, sizeof(EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)))); if (Rsdp->Revision >= 2) { DEBUG ((EFI_D_INFO, "(TXT) RSDP Length - %08x\n", Rsdp->Length)); DEBUG ((EFI_D_INFO, "(TXT) RSDP ExtendedChecksum - %02x\n", CalculateCheckSum8((UINT8 *)Rsdp, Rsdp->Length))); } Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress; DEBUG ((EFI_D_INFO, "(TXT) RSDT Address - %08x\n", Rsdt)); DEBUG ((EFI_D_INFO, "(TXT) RSDT Length - %08x\n", Rsdt->Length)); DEBUG ((EFI_D_INFO, "(TXT) RSDT Checksum - %02x\n", CalculateCheckSum8((UINT8 *)Rsdt, Rsdt->Length))); if (Rsdp->Revision >= 2) { Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress; DEBUG ((EFI_D_INFO, "(TXT) XSDT Address - %016lx\n", Xsdt)); DEBUG ((EFI_D_INFO, "(TXT) XSDT Length - %08x\n", Xsdt->Length)); DEBUG ((EFI_D_INFO, "(TXT) XSDT Checksum - %02x\n", CalculateCheckSum8((UINT8 *)Xsdt, Xsdt->Length))); } } return ; }
/** Publish and remove the iSCSI Boot Firmware Table according to the iSCSI session status. **/ VOID IScsiPublishIbft ( VOID ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINT8 *Heap; UINT8 Checksum; UINTN Index; EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; EFI_ACPI_DESCRIPTION_HEADER *Rsdt; Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol); if (EFI_ERROR (Status)) { return ; } // // Find ACPI table RSD_PTR from system table // for (Index = 0, Rsdp = NULL; Index < gST->NumberOfTableEntries; Index++) { if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid) || CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid) || CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpiTableGuid) ) { // // A match was found. // Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) gST->ConfigurationTable[Index].VendorTable; break; } } if (Rsdp == NULL) { return ; } else { Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress; } if (mIbftInstalled) { Status = AcpiTableProtocol->UninstallAcpiTable ( AcpiTableProtocol, mTableKey ); if (EFI_ERROR (Status)) { return ; } mIbftInstalled = FALSE; } // // Get all iSCSI private protocols. // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiCallerIdGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { return ; } // // Allocate 4k bytes to hold the ACPI table. // Table = AllocateZeroPool (IBFT_MAX_SIZE); if (Table == NULL) { return ; } Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET; // // Fill in the various section of the iSCSI Boot Firmware Table. // IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId); IScsiInitControlSection (Table, HandleCount); IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]); IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer); Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length); Table->Checksum = Checksum; FreePool (HandleBuffer); // // Install or update the iBFT table. // Status = AcpiTableProtocol->InstallAcpiTable ( AcpiTableProtocol, Table, Table->Length, &mTableKey ); if (EFI_ERROR(Status)) { return; } mIbftInstalled = TRUE; FreePool (Table); }
EFI_STATUS AcpiPlatformEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; INTN Instance; EFI_ACPI_COMMON_HEADER *CurrentTable; UINTN TableHandle; UINT32 FvStatus; UINTN Size; EFI_ACPI_TABLE_VERSION Version; QNC_DEVICE_ENABLES QNCDeviceEnables; EFI_HANDLE Handle; UINTN Index; PCI_DEVICE_INFO *PciDeviceInfo; EFI_ACPI_HANDLE PciRootHandle; BOOLEAN UpdatePRT; BOOLEAN UpdatePRW; PCI_DEVICE_SETTING *mConfigData; Instance = 0; TableHandle = 0; CurrentTable = NULL; mConfigData = NULL; QNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables); // // Initialize the EFI Driver Library // ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512); Status = gBS->AllocatePool ( EfiACPIMemoryNVS, sizeof (EFI_GLOBAL_NVS_AREA), (VOID**)&mGlobalNvsArea.Area ); Handle = NULL; Status = gBS->InstallProtocolInterface ( &Handle, &gEfiGlobalNvsAreaProtocolGuid, EFI_NATIVE_INTERFACE, &mGlobalNvsArea ); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (Status)) { SetMem ( mGlobalNvsArea.Area, sizeof (EFI_GLOBAL_NVS_AREA), 0 ); } // // Initialize the data. Eventually, this will be controlled by setup options. // mGlobalNvsArea.Area->HpetEnable = PcdGetBool (PcdHpetEnable); mGlobalNvsArea.Area->Pm1blkIoBaseAddress = PcdGet16(PcdPm1blkIoBaseAddress); mGlobalNvsArea.Area->PmbaIoBaseAddress = PcdGet16(PcdPmbaIoBaseAddress); mGlobalNvsArea.Area->Gpe0blkIoBaseAddress = PcdGet16(PcdGpe0blkIoBaseAddress); mGlobalNvsArea.Area->GbaIoBaseAddress = PcdGet16(PcdGbaIoBaseAddress); mGlobalNvsArea.Area->SmbaIoBaseAddress = PcdGet16(PcdSmbaIoBaseAddress); mGlobalNvsArea.Area->SpiDmaIoBaseAddress = PcdGet16(PcdSpiDmaIoBaseAddress); mGlobalNvsArea.Area->WdtbaIoBaseAddress = PcdGet16(PcdWdtbaIoBaseAddress); mGlobalNvsArea.Area->HpetBaseAddress = (UINT32)PcdGet64(PcdHpetBaseAddress); mGlobalNvsArea.Area->HpetSize = (UINT32)PcdGet64(PcdHpetSize); mGlobalNvsArea.Area->PciExpressBaseAddress= (UINT32)PcdGet64(PcdPciExpressBaseAddress); mGlobalNvsArea.Area->PciExpressSize = (UINT32)PcdGet64(PcdPciExpressSize); mGlobalNvsArea.Area->RcbaMmioBaseAddress = (UINT32)PcdGet64(PcdRcbaMmioBaseAddress); mGlobalNvsArea.Area->RcbaMmioSize = (UINT32)PcdGet64(PcdRcbaMmioSize); mGlobalNvsArea.Area->IoApicBaseAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress); mGlobalNvsArea.Area->IoApicSize = (UINT32)PcdGet64(PcdIoApicSize); mGlobalNvsArea.Area->TpmPresent = (UINT32)(FALSE); // // Find the AcpiTable protocol // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Initialize MADT table // Status = MadtTableInitialize (&CurrentTable, &Size); ASSERT_EFI_ERROR (Status); // // Perform any table specific updates. // AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version); // // Update the check sum // It needs to be zeroed before the checksum calculation // ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0; ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length); // // Add the table // TableHandle = 0; Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, CurrentTable->Length, &TableHandle ); ASSERT_EFI_ERROR (Status); CurrentTable = NULL; // // Init Pci Device PRT PRW information structure from PCD // mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING)); ASSERT_EFI_ERROR (mConfigData); InitPciDeviceInfoStructure (mConfigData); // // Get the Acpi SDT protocol for manipulation on acpi table // Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt); ASSERT_EFI_ERROR (Status); // // Locate the firmware volume protocol // Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // // Read tables from the storage file. // while (Status == EFI_SUCCESS) { Status = FwVol->ReadSection ( FwVol, (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile), EFI_SECTION_RAW, Instance, (VOID**)&CurrentTable, &Size, &FvStatus ); if (!EFI_ERROR(Status)) { // // Perform any table specific updates. // AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version); // // Update the check sum // It needs to be zeroed before the checksum calculation // ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0; ((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length); // // Add the table // TableHandle = 0; Status = AcpiTable->InstallAcpiTable ( AcpiTable, CurrentTable, ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length, &TableHandle ); if (EFI_ERROR(Status)) { return EFI_ABORTED; } // // If this table is the DSDT table, then update the _PRT and _PRW based on // the settings from pcds // if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { // // Create the root handle for DSDT table // Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle); ASSERT_EFI_ERROR (Status); PciRootHandle = NULL; PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle); ASSERT (PciRootHandle != NULL); PciDeviceInfo = NULL; for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) { PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]); // // Check whether this is a valid item // if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) { //DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress)); UpdatePRT = FALSE; UpdatePRW = FALSE; SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW); // // Check whether there is any valid pci routing item // if (UpdatePRT) { // // Update the pci routing information // //DEBUG ((EFI_D_ERROR, "Update _PRT\n")); SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo); } // // Check whether there is any valid pci routing item // if (UpdatePRW) { // // Update the pci wakeup information // //DEBUG ((EFI_D_ERROR, "Update _PRW\n")); SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo); } } } Status = mAcpiSdt->Close (PciRootHandle); ASSERT_EFI_ERROR (Status); // // Mark the root handle as modified , let SDT protocol recaculate the checksum // ((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE; Status = mAcpiSdt->Close (mDsdtHandle); ASSERT_EFI_ERROR (Status); } // // Increment the instance // Instance++; CurrentTable = NULL; } } gBS->FreePool (mConfigData); return EFI_SUCCESS; }
/** Publish and remove the iSCSI Boot Firmware Table according to the iSCSI session status. **/ VOID IScsiPublishIbft ( VOID ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table; UINTN HandleCount; EFI_HANDLE *HandleBuffer; UINT8 *Heap; UINT8 Checksum; EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; EFI_ACPI_DESCRIPTION_HEADER *Rsdt; EFI_ACPI_DESCRIPTION_HEADER *Xsdt; Rsdt = NULL; Xsdt = NULL; Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol); if (EFI_ERROR (Status)) { return ; } // // Find ACPI table RSD_PTR from system table // Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp); if (EFI_ERROR (Status)) { Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) &Rsdp); } if (EFI_ERROR (Status) || (Rsdp == NULL)) { return ; } else if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION && Rsdp->XsdtAddress != 0) { Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress; } else if (Rsdp->RsdtAddress != 0) { Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress; } if ((Xsdt == NULL) && (Rsdt == NULL)) { return ; } if (mIbftInstalled) { Status = AcpiTableProtocol->UninstallAcpiTable ( AcpiTableProtocol, mTableKey ); if (EFI_ERROR (Status)) { return ; } mIbftInstalled = FALSE; } // // Get all iSCSI private protocols. // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiCallerIdGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { return ; } // // Allocate 4k bytes to hold the ACPI table. // Table = AllocateZeroPool (IBFT_MAX_SIZE); if (Table == NULL) { return ; } Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET; // // Fill in the various section of the iSCSI Boot Firmware Table. // if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) { IScsiInitIbfTableHeader (Table, Xsdt->OemId, &Xsdt->OemTableId); } else { IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId); } IScsiInitControlSection (Table, HandleCount); IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]); IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer); Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length); Table->Checksum = Checksum; FreePool (HandleBuffer); // // Install or update the iBFT table. // Status = AcpiTableProtocol->InstallAcpiTable ( AcpiTableProtocol, Table, Table->Length, &mTableKey ); if (EFI_ERROR(Status)) { return; } mIbftInstalled = TRUE; FreePool (Table); }
/** Create UX capsule. @retval EFI_SUCCESS The capsule header is appended. @retval EFI_UNSUPPORTED Input parameter is not valid. @retval EFI_OUT_OF_RESOURCES No enough resource to create UX capsule. **/ EFI_STATUS CreateBmpFmp ( VOID ) { CHAR16 *OutputCapsuleName; VOID *BmpBuffer; UINTN FileSize; CHAR16 *BmpName; UINT8 *FullCapsuleBuffer; UINTN FullCapsuleBufferSize; EFI_DISPLAY_CAPSULE *DisplayCapsule; EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: NO GOP is found.\n"); return EFI_UNSUPPORTED; } Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode); Print(L"HorizontalResolution - %d, ", Gop->Mode->Info->HorizontalResolution); Print(L"VerticalResolution - %d\n", Gop->Mode->Info->VerticalResolution); // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight if (Argc != 5) { Print(L"CapsuleApp: Invalid Parameter.\n"); return EFI_UNSUPPORTED; } if (StrCmp(Argv[3], L"-O") != 0) { Print(L"CapsuleApp: NO output capsule name.\n"); return EFI_UNSUPPORTED; } OutputCapsuleName = Argv[4]; BmpBuffer = NULL; FileSize = 0; FullCapsuleBuffer = NULL; BmpName = Argv[2]; Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName); goto Done; } FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize; FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize); if (FullCapsuleBuffer == NULL) { Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize); Status = EFI_OUT_OF_RESOURCES; goto Done; } DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer; CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid); DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader); DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize; DisplayCapsule->ImagePayload.Version = 1; DisplayCapsule->ImagePayload.Checksum = 0; DisplayCapsule->ImagePayload.ImageType = 0; // BMP DisplayCapsule->ImagePayload.Reserved = 0; DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode; DisplayCapsule->ImagePayload.OffsetX = 0; DisplayCapsule->ImagePayload.OffsetY = 0; CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize); DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer, FullCapsuleBufferSize); Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer); Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status); Done: if (BmpBuffer != NULL) { FreePool(BmpBuffer); } if (FullCapsuleBuffer != NULL) { FreePool(FullCapsuleBuffer); } return Status; }
EFI_STATUS ConvertMpsTable ( IN OUT VOID **Table ) /*++ Routine Description: Convert MP Table if the Location of the SMBios Table is lower than Address 0x100000 Assumption here: As in legacy Bios, MP table is required to place in E/F Seg, So here we just check if the range is E/F seg, and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData Arguments: Table - pointer to the table Returns: EFI_SUCCESS - Convert Table successfully Other - Failed --*/ { UINT32 Data32; UINT32 FPLength; EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri; EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew; EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri; EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew; VOID *OemTableOri; VOID *OemTableNew; EFI_STATUS Status; EFI_PHYSICAL_ADDRESS BufferPtr; // // Get MP configuration Table // MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*Table); // // Get Floating pointer structure length // FPLength = MpsFloatingPointerOri->Length * 16; ASSERT(CalculateSum8((UINT8*)MpsFloatingPointerOri, FPLength) == 0); Data32 = FPLength + SYS_TABLE_PAD (FPLength); MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress); ASSERT(MpsTableOri != NULL); ASSERT(CalculateSum8((UINT8*)MpsTableOri, MpsTableOri->BaseTableLength) == 0); Data32 += MpsTableOri->BaseTableLength; Data32 += MpsTableOri->ExtendedTableLength; if (MpsTableOri->OemTablePointer != 0x00) { Data32 += SYS_TABLE_PAD (Data32); Data32 += MpsTableOri->OemTableSize; } // // Relocate memory // BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES(Data32), &BufferPtr ); ASSERT_EFI_ERROR (Status); MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr; CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength); // // If Mp Table exists // if (MpsTableOri != NULL) { // // Get Mps table length, including Ext table // BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength); MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr; CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength); if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){ BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength; BufferPtr += SYS_TABLE_PAD (BufferPtr); OemTableNew = (VOID *)(UINTN)BufferPtr; OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer; CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize); MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew; } MpsTableNew->Checksum = 0; MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength); MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew; MpsFloatingPointerNew->Checksum = 0; MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength); } // // Change the pointer // *Table = MpsFloatingPointerNew; return EFI_SUCCESS; }
EFI_STATUS ConvertSmbiosTable ( IN OUT VOID **Table ) /*++ Routine Description: Convert Smbios Table if the Location of the SMBios Table is lower than Address 0x100000 Assumption here: As in legacy Bios, Smbios table is required to place in E/F Seg, So here we just check if the range is F seg, and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData Arguments: Table - pointer to the table Returns: EFI_SUCCESS - Convert Table successfully Other - Failed --*/ { SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew; SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri; EFI_STATUS Status; UINT32 SmbiosEntryLen; UINT32 BufferLen; EFI_PHYSICAL_ADDRESS BufferPtr; SmbiosTableNew = NULL; SmbiosTableOri = NULL; // // Get Smibos configuration Table // SmbiosTableOri = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)((*Table)); ASSERT(CalculateSum8((UINT8*)SmbiosTableOri, sizeof(SMBIOS_TABLE_ENTRY_POINT)) == 0); // // Relocate the Smibos memory // BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS; if (SmbiosTableOri->SmbiosBcdRevision != 0x21) { SmbiosEntryLen = SmbiosTableOri->EntryPointLength; } else { // // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1 // SmbiosEntryLen = 0x1F; } BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES(BufferLen), &BufferPtr ); ASSERT_EFI_ERROR (Status); SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr; CopyMem ( SmbiosTableNew, SmbiosTableOri, SmbiosEntryLen ); // // Get Smbios Structure table address, and make sure the start address is 32-bit align // BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen); CopyMem ( (VOID *)(UINTN)BufferPtr, (VOID *)(UINTN)(SmbiosTableOri->TableAddress), SmbiosTableOri->TableLength ); SmbiosTableNew->TableAddress = (UINT32)BufferPtr; SmbiosTableNew->IntermediateChecksum = 0; SmbiosTableNew->IntermediateChecksum = CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10); // // Change the SMBIOS pointer // *Table = SmbiosTableNew; return EFI_SUCCESS; }
/** Create UX capsule. @retval EFI_SUCCESS The capsule header is appended. @retval EFI_UNSUPPORTED Input parameter is not valid. @retval EFI_OUT_OF_RESOURCES No enough resource to create UX capsule. **/ EFI_STATUS CreateBmpFmp ( VOID ) { CHAR16 *OutputCapsuleName; VOID *BmpBuffer; UINTN FileSize; CHAR16 *BmpName; UINT8 *FullCapsuleBuffer; UINTN FullCapsuleBufferSize; EFI_DISPLAY_CAPSULE *DisplayCapsule; EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBlt; UINTN GopBltSize; UINTN Height; UINTN Width; Status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID **)&Gop); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: NO GOP is found.\n"); return EFI_UNSUPPORTED; } Info = Gop->Mode->Info; Print(L"Current GOP: Mode - %d, ", Gop->Mode->Mode); Print(L"HorizontalResolution - %d, ", Info->HorizontalResolution); Print(L"VerticalResolution - %d\n", Info->VerticalResolution); // HorizontalResolution >= BMP_IMAGE_HEADER.PixelWidth // VerticalResolution >= BMP_IMAGE_HEADER.PixelHeight if (Argc != 5) { Print(L"CapsuleApp: Incorrect parameter count.\n"); return EFI_UNSUPPORTED; } if (StrCmp(Argv[3], L"-O") != 0) { Print(L"CapsuleApp: NO output capsule name.\n"); return EFI_UNSUPPORTED; } OutputCapsuleName = Argv[4]; BmpBuffer = NULL; FileSize = 0; FullCapsuleBuffer = NULL; BmpName = Argv[2]; Status = ReadFileToBuffer(BmpName, &FileSize, &BmpBuffer); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: BMP image (%s) is not found.\n", BmpName); goto Done; } GopBlt = NULL; Status = TranslateBmpToGopBlt ( BmpBuffer, FileSize, &GopBlt, &GopBltSize, &Height, &Width ); if (EFI_ERROR(Status)) { Print(L"CapsuleApp: BMP image (%s) is not valid.\n", BmpName); goto Done; } if (GopBlt != NULL) { FreePool (GopBlt); } Print(L"BMP image (%s), Width - %d, Height - %d\n", BmpName, Width, Height); if (Height > Info->VerticalResolution) { Status = EFI_INVALID_PARAMETER; Print(L"CapsuleApp: BMP image (%s) height is larger than current resolution.\n", BmpName); goto Done; } if (Width > Info->HorizontalResolution) { Status = EFI_INVALID_PARAMETER; Print(L"CapsuleApp: BMP image (%s) width is larger than current resolution.\n", BmpName); goto Done; } FullCapsuleBufferSize = sizeof(EFI_DISPLAY_CAPSULE) + FileSize; FullCapsuleBuffer = AllocatePool(FullCapsuleBufferSize); if (FullCapsuleBuffer == NULL) { Print(L"CapsuleApp: Capsule Buffer size (0x%x) too big.\n", FullCapsuleBufferSize); Status = EFI_OUT_OF_RESOURCES; goto Done; } DisplayCapsule = (EFI_DISPLAY_CAPSULE *)FullCapsuleBuffer; CopyGuid(&DisplayCapsule->CapsuleHeader.CapsuleGuid, &gWindowsUxCapsuleGuid); DisplayCapsule->CapsuleHeader.HeaderSize = sizeof(DisplayCapsule->CapsuleHeader); DisplayCapsule->CapsuleHeader.Flags = CAPSULE_FLAGS_PERSIST_ACROSS_RESET; DisplayCapsule->CapsuleHeader.CapsuleImageSize = (UINT32)FullCapsuleBufferSize; DisplayCapsule->ImagePayload.Version = 1; DisplayCapsule->ImagePayload.Checksum = 0; DisplayCapsule->ImagePayload.ImageType = 0; // BMP DisplayCapsule->ImagePayload.Reserved = 0; DisplayCapsule->ImagePayload.Mode = Gop->Mode->Mode; // // Center the bitmap horizontally // DisplayCapsule->ImagePayload.OffsetX = (UINT32)((Info->HorizontalResolution - Width) / 2); // // Put bitmap 3/4 down the display. If bitmap is too tall, then align bottom // of bitmap at bottom of display. // DisplayCapsule->ImagePayload.OffsetY = MIN ( (UINT32)(Info->VerticalResolution - Height), (UINT32)(((3 * Info->VerticalResolution) - (2 * Height)) / 4) ); Print(L"BMP image (%s), OffsetX - %d, OffsetY - %d\n", BmpName, DisplayCapsule->ImagePayload.OffsetX, DisplayCapsule->ImagePayload.OffsetY ); CopyMem((DisplayCapsule + 1), BmpBuffer, FileSize); DisplayCapsule->ImagePayload.Checksum = CalculateCheckSum8(FullCapsuleBuffer, FullCapsuleBufferSize); Status = WriteFileFromBuffer(OutputCapsuleName, FullCapsuleBufferSize, FullCapsuleBuffer); Print(L"CapsuleApp: Write %s %r\n", OutputCapsuleName, Status); Done: if (BmpBuffer != NULL) { FreePool(BmpBuffer); } if (FullCapsuleBuffer != NULL) { FreePool(FullCapsuleBuffer); } return Status; }