/** Copy AuthSessionIn to TPM2 command buffer. @param [in] AuthSessionIn Input AuthSession data @param [out] AuthSessionOut Output AuthSession data in TPM2 command buffer @return AuthSession size **/ UINT32 EFIAPI CopyAuthSessionCommand ( IN TPMS_AUTH_COMMAND *AuthSessionIn, OPTIONAL OUT UINT8 *AuthSessionOut ) { UINT8 *Buffer; Buffer = (UINT8 *)AuthSessionOut; // // Add in Auth session // if (AuthSessionIn != NULL) { // sessionHandle WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(AuthSessionIn->sessionHandle)); Buffer += sizeof(UINT32); // nonce WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->nonce.size)); Buffer += sizeof(UINT16); CopyMem (Buffer, AuthSessionIn->nonce.buffer, AuthSessionIn->nonce.size); Buffer += AuthSessionIn->nonce.size; // sessionAttributes *(UINT8 *)Buffer = *(UINT8 *)&AuthSessionIn->sessionAttributes; Buffer++; // hmac WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthSessionIn->hmac.size)); Buffer += sizeof(UINT16); CopyMem (Buffer, AuthSessionIn->hmac.buffer, AuthSessionIn->hmac.size); Buffer += AuthSessionIn->hmac.size; } else { // sessionHandle WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(TPM_RS_PW)); Buffer += sizeof(UINT32); // nonce = nullNonce WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0)); Buffer += sizeof(UINT16); // sessionAttributes = 0 *(UINT8 *)Buffer = 0x00; Buffer++; // hmac = nullAuth WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(0)); Buffer += sizeof(UINT16); } return (UINT32)(UINTN)(Buffer - (UINT8 *)AuthSessionOut); }
/** Reads from a given location in the PCI configuration space. @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param This Pointer to local data for the interface. @param Width The width of the access. Enumerated in bytes. See EFI_PEI_PCI_CFG_PPI_WIDTH above. @param Address The physical address of the access. The format of the address is described by EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS. @param Buffer A pointer to the buffer of data. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER The invalid access width. **/ EFI_STATUS EFIAPI PciCfg2Read ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_PCI_CFG2_PPI *This, IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, IN UINT64 Address, IN OUT VOID *Buffer ) { UINTN PciLibAddress; PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address); if (Width == EfiPeiPciCfgWidthUint8) { *((UINT8 *) Buffer) = PciRead8 (PciLibAddress); } else if (Width == EfiPeiPciCfgWidthUint16) { if ((PciLibAddress & 0x01) == 0) { // // Aligned Pci address access // WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress)); } else { // // Unaligned Pci address access, break up the request into byte by byte. // *((UINT8 *) Buffer) = PciRead8 (PciLibAddress); *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1); } } else if (Width == EfiPeiPciCfgWidthUint32) { if ((PciLibAddress & 0x03) == 0) { // // Aligned Pci address access // WriteUnaligned32 (((UINT32 *) Buffer), PciRead32 (PciLibAddress)); } else if ((PciLibAddress & 0x01) == 0) { // // Unaligned Pci address access, break up the request into word by word. // WriteUnaligned16 (((UINT16 *) Buffer), PciRead16 (PciLibAddress)); WriteUnaligned16 (((UINT16 *) Buffer + 1), PciRead16 (PciLibAddress + 2)); } else { // // Unaligned Pci address access, break up the request into byte by byte. // *((UINT8 *) Buffer) = PciRead8 (PciLibAddress); *((UINT8 *) Buffer + 1) = PciRead8 (PciLibAddress + 1); *((UINT8 *) Buffer + 2) = PciRead8 (PciLibAddress + 2); *((UINT8 *) Buffer + 3) = PciRead8 (PciLibAddress + 3); } } else { return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
/** This command allows options in authorizations without requiring that the TPM evaluate all of the options. If a policy may be satisfied by different sets of conditions, the TPM need only evaluate one set that satisfies the policy. This command will indicate that one of the required sets of conditions has been satisfied. @param[in] PolicySession Handle for the policy session being extended. @param[in] HashList the list of hashes to check for a match. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PolicyOR ( IN TPMI_SH_POLICY PolicySession, IN TPML_DIGEST *HashList ) { EFI_STATUS Status; TPM2_POLICY_OR_COMMAND SendBuffer; TPM2_POLICY_OR_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; UINTN Index; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicyOR); SendBuffer.PolicySession = SwapBytes32 (PolicySession); Buffer = (UINT8 *)&SendBuffer.HashList; WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (HashList->count)); Buffer += sizeof(UINT32); for (Index = 0; Index < HashList->count; Index++) { WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (HashList->digests[Index].size)); Buffer += sizeof(UINT16); CopyMem (Buffer, HashList->digests[Index].buffer, HashList->digests[Index].size); Buffer += HashList->digests[Index].size; } SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PolicyOR - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** Reads memory-mapped registers. @param[in] PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param[in] This Pointer to local data for the interface. @param[in] Width The width of the access. Enumerated in bytes. @param[in] Address The physical address of the access. @param[in] Count The number of accesses to perform. @param[out] Buffer A pointer to the buffer of data. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. @retval EFI_INVALID_PARAMETER Buffer is NULL. @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count is not valid for this EFI system. **/ EFI_STATUS EFIAPI CpuMemoryServiceRead ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_CPU_IO_PPI *This, IN EFI_PEI_CPU_IO_PPI_WIDTH Width, IN UINT64 Address, IN UINTN Count, OUT VOID *Buffer ) { EFI_STATUS Status; UINT8 InStride; UINT8 OutStride; EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth; BOOLEAN Aligned; UINT8 *Uint8Buffer; Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } // // Select loop based on the width of the transfer // InStride = mInStride[Width]; OutStride = mOutStride[Width]; OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03); Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00); for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { if (OperationWidth == EfiPeiCpuIoWidthUint8) { *Uint8Buffer = MmioRead8 ((UINTN)Address); } else if (OperationWidth == EfiPeiCpuIoWidthUint16) { if (Aligned) { *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address); } else { WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint32) { if (Aligned) { *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address); } else { WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint64) { if (Aligned) { *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address); } else { WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address)); } } } return EFI_SUCCESS; }
/** Sets the length, in bytes, of a device path node. Sets the length of the device path node specified by Node to the value specified by NodeLength. NodeLength is returned. Node is not required to be aligned on a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16() be used to set the contents of the Length field. If Node is NULL, then ASSERT(). If NodeLength >= SIZE_64KB, then ASSERT(). If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT(). @param Node A pointer to a device path node data structure. @param Length The length, in bytes, of the device path node. @return Length **/ UINT16 EFIAPI SetDevicePathNodeLength ( IN OUT VOID *Node, IN UINTN Length ) { ASSERT (Node != NULL); ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB)); return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length)); }
/** Execute READ (10) SCSI command on a specific UFS device. @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure. @param[in] Lun The lun on which the SCSI cmd executed. @param[in] StartLba The start LBA. @param[in] SectorNum The sector number to be read. @param[out] DataBuffer A pointer to data buffer. @param[out] DataLength The length of output data. @param[out] SenseData A pointer to output sense data. @param[out] SenseDataLength The length of output sense data. @retval EFI_SUCCESS The command executed successfully. @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet. @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. **/ EFI_STATUS UfsPeimRead10 ( IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINTN Lun, IN UINTN StartLba, IN UINT32 SectorNum, OUT VOID *DataBuffer, OUT UINT32 *DataLength, OUT VOID *SenseData, OPTIONAL OUT UINT8 *SenseDataLength ) { UFS_SCSI_REQUEST_PACKET Packet; UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN]; EFI_STATUS Status; ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET)); ZeroMem (Cdb, sizeof (Cdb)); Cdb[0] = EFI_SCSI_OP_READ10; WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 ((UINT32) StartLba)); WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorNum)); Packet.Timeout = UFS_TIMEOUT; Packet.Cdb = Cdb; Packet.CdbLength = sizeof (Cdb); Packet.InDataBuffer = DataBuffer; Packet.InTransferLength = *DataLength; Packet.DataDirection = UfsDataIn; Packet.SenseData = SenseData; Packet.SenseDataLength = *SenseDataLength; Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet); if (*SenseDataLength != 0) { *SenseDataLength = Packet.SenseDataLength; } if (!EFI_ERROR (Status)) { *DataLength = Packet.InTransferLength; } return Status; }
/** Issue TSC_PhysicalPresence command to TPM. @param[in] TcgProtocol EFI TCG Protocol instance. @param[in] PhysicalPresence The state to set the TPM's Physical Presence flags. @retval EFI_SUCCESS TPM executed the command successfully. @retval EFI_SECURITY_VIOLATION TPM returned error when executing the command. @retval other Failed to locate EFI TCG Protocol. **/ EFI_STATUS TpmPhysicalPresence ( IN EFI_TCG_PROTOCOL *TcgProtocol, IN TPM_PHYSICAL_PRESENCE PhysicalPresence ) { EFI_STATUS Status; TPM_RQU_COMMAND_HDR *TpmRqu; TPM_PHYSICAL_PRESENCE *TpmPp; TPM_RSP_COMMAND_HDR TpmRsp; UINT8 Buffer[sizeof (*TpmRqu) + sizeof (*TpmPp)]; TpmRqu = (TPM_RQU_COMMAND_HDR*)Buffer; TpmPp = (TPM_PHYSICAL_PRESENCE*)(TpmRqu + 1); TpmRqu->tag = SwapBytes16 (TPM_TAG_RQU_COMMAND); TpmRqu->paramSize = SwapBytes32 (sizeof (Buffer)); TpmRqu->ordinal = SwapBytes32 (TSC_ORD_PhysicalPresence); WriteUnaligned16 (TpmPp, (TPM_PHYSICAL_PRESENCE) SwapBytes16 (PhysicalPresence)); Status = TcgProtocol->PassThroughToTpm ( TcgProtocol, sizeof (Buffer), (UINT8*)TpmRqu, sizeof (TpmRsp), (UINT8*)&TpmRsp ); ASSERT_EFI_ERROR (Status); ASSERT (TpmRsp.tag == SwapBytes16 (TPM_TAG_RSP_COMMAND)); if (TpmRsp.returnCode != 0) { // // If it fails, some requirements may be needed for this command. // return EFI_SECURITY_VIOLATION; } return Status; }
/** Patch the immediate operand of an IA32 or X64 instruction such that the byte, word, dword or qword operand is encoded at the end of the instruction's binary representation. This function should be used to update object code that was compiled with NASM from assembly source code. Example: NASM source code: mov eax, strict dword 0 ; the imm32 zero operand will be patched ASM_PFX(gPatchCr3): mov cr3, eax C source code: X86_ASSEMBLY_PATCH_LABEL gPatchCr3; PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4); @param[out] InstructionEnd Pointer right past the instruction to patch. The immediate operand to patch is expected to comprise the trailing bytes of the instruction. If InstructionEnd is closer to address 0 than ValueSize permits, then ASSERT(). @param[in] PatchValue The constant to write to the immediate operand. The caller is responsible for ensuring that PatchValue can be represented in the byte, word, dword or qword operand (as indicated through ValueSize); otherwise ASSERT(). @param[in] ValueSize The size of the operand in bytes; must be 1, 2, 4, or 8. ASSERT() otherwise. **/ VOID EFIAPI PatchInstructionX86 ( OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd, IN UINT64 PatchValue, IN UINTN ValueSize ) { // // The equality ((UINTN)InstructionEnd == ValueSize) would assume a zero-size // instruction at address 0; forbid it. // ASSERT ((UINTN)InstructionEnd > ValueSize); switch (ValueSize) { case 1: ASSERT (PatchValue <= MAX_UINT8); *((UINT8 *)(UINTN)InstructionEnd - 1) = (UINT8)PatchValue; break; case 2: ASSERT (PatchValue <= MAX_UINT16); WriteUnaligned16 ((UINT16 *)(UINTN)InstructionEnd - 1, (UINT16)PatchValue); break; case 4: ASSERT (PatchValue <= MAX_UINT32); WriteUnaligned32 ((UINT32 *)(UINTN)InstructionEnd - 1, (UINT32)PatchValue); break; case 8: WriteUnaligned64 ((UINT64 *)(UINTN)InstructionEnd - 1, PatchValue); break; default: ASSERT (FALSE); } }
/** This command includes a secret-based authorization to a policy. The caller proves knowledge of the secret value using an authorization session using the authValue associated with authHandle. @param[in] AuthHandle Handle for an entity providing the authorization @param[in] PolicySession Handle for the policy session being extended. @param[in] AuthSession Auth Session context @param[in] NonceTPM The policy nonce for the session. @param[in] CpHashA Digest of the command parameters to which this authorization is limited. @param[in] PolicyRef A reference to a policy relating to the authorization. @param[in] Expiration Time when authorization will expire, measured in seconds from the time that nonceTPM was generated. @param[out] Timeout Time value used to indicate to the TPM when the ticket expires. @param[out] PolicyTicket A ticket that includes a value indicating when the authorization expires. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PolicySecret ( IN TPMI_DH_ENTITY AuthHandle, IN TPMI_SH_POLICY PolicySession, IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL IN TPM2B_NONCE *NonceTPM, IN TPM2B_DIGEST *CpHashA, IN TPM2B_NONCE *PolicyRef, IN INT32 Expiration, OUT TPM2B_TIMEOUT *Timeout, OUT TPMT_TK_AUTH *PolicyTicket ) { EFI_STATUS Status; TPM2_POLICY_SECRET_COMMAND SendBuffer; TPM2_POLICY_SECRET_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; UINT32 SessionInfoSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_PolicySecret); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); SendBuffer.PolicySession = SwapBytes32 (PolicySession); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // Real data // WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(NonceTPM->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, NonceTPM->buffer, NonceTPM->size); Buffer += NonceTPM->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(CpHashA->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, CpHashA->buffer, CpHashA->size); Buffer += CpHashA->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PolicyRef->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, PolicyRef->buffer, PolicyRef->size); Buffer += PolicyRef->size; WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32((UINT32)Expiration)); Buffer += sizeof(UINT32); SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { goto Done; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - RecvBufferSize Error - %x\n", RecvBufferSize)); Status = EFI_DEVICE_ERROR; goto Done; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PolicySecret - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); Status = EFI_DEVICE_ERROR; goto Done; } // // Return the response // Buffer = (UINT8 *)&RecvBuffer.Timeout; Timeout->size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); if (Timeout->size > sizeof(UINT64)) { DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - Timeout->size error %x\n", Timeout->size)); Status = EFI_DEVICE_ERROR; goto Done; } Buffer += sizeof(UINT16); CopyMem (Timeout->buffer, Buffer, Timeout->size); PolicyTicket->tag = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); Buffer += sizeof(UINT16); PolicyTicket->hierarchy = SwapBytes32(ReadUnaligned32 ((UINT32 *)Buffer)); Buffer += sizeof(UINT32); PolicyTicket->digest.size = SwapBytes16(ReadUnaligned16 ((UINT16 *)Buffer)); Buffer += sizeof(UINT16); if (PolicyTicket->digest.size > sizeof(TPMU_HA)) { DEBUG ((DEBUG_ERROR, "Tpm2PolicySecret - digest.size error %x\n", PolicyTicket->digest.size)); Status = EFI_DEVICE_ERROR; goto Done; } CopyMem (PolicyTicket->digest.buffer, Buffer, PolicyTicket->digest.size); Done: // // Clear AuthSession Content // ZeroMem (&SendBuffer, sizeof(SendBuffer)); ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); return Status; }
/** This command defines the attributes of an NV Index and causes the TPM to reserve space to hold the data associated with the index. If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED. @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. @param[in] AuthSession Auth Session context @param[in] Auth The authorization data. @param[in] NvPublic The public area of the index. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. @retval EFI_ALREADY_STARTED The command was returned successfully, but NvIndex is already defined. **/ EFI_STATUS EFIAPI Tpm2NvDefineSpace ( IN TPMI_RH_PROVISION AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL IN TPM2B_AUTH *Auth, IN TPM2B_NV_PUBLIC *NvPublic ) { EFI_STATUS Status; TPM2_NV_DEFINESPACE_COMMAND SendBuffer; TPM2_NV_DEFINESPACE_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT16 NvPublicSize; UINT8 *Buffer; UINT32 SessionInfoSize; TPM_RC ResponseCode; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // IndexAuth // WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size)); Buffer += sizeof(UINT16); CopyMem(Buffer, Auth->buffer, Auth->size); Buffer += Auth->size; // // NvPublic // NvPublicSize = NvPublic->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex)); Buffer += sizeof(UINT32); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); Buffer += sizeof(UINT32); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size)); Buffer += sizeof(UINT16); CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size); Buffer += NvPublic->nvPublic.authPolicy.size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize)); Buffer += sizeof(UINT16); SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { goto Done; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); Status = EFI_DEVICE_ERROR; goto Done; } ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); if (ResponseCode != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); } switch (ResponseCode) { case TPM_RC_SUCCESS: // return data break; case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo: case TPM_RC_SIZE + RC_NV_DefineSpace_auth: Status = EFI_BAD_BUFFER_SIZE; break; case TPM_RC_ATTRIBUTES: case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo: Status = EFI_UNSUPPORTED; break; case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle: Status = EFI_INVALID_PARAMETER; break; case TPM_RC_NV_DEFINED: Status = EFI_ALREADY_STARTED; break; case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo: case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle: Status = EFI_INVALID_PARAMETER; break; case TPM_RC_NV_SPACE: Status = EFI_OUT_OF_RESOURCES; break; default: Status = EFI_DEVICE_ERROR; break; } Done: // // Clear AuthSession Content // ZeroMem (&SendBuffer, sizeof(SendBuffer)); ZeroMem (&RecvBuffer, sizeof(RecvBuffer)); return Status; }
/** This command is used to start an authorization session using alternative methods of establishing the session key (sessionKey) that is used for authorization and encrypting value. @param[in] TpmKey Handle of a loaded decrypt key used to encrypt salt. @param[in] Bind Entity providing the authValue. @param[in] NonceCaller Initial nonceCaller, sets nonce size for the session. @param[in] Salt Value encrypted according to the type of tpmKey. @param[in] SessionType Indicates the type of the session. @param[in] Symmetric The algorithm and key size for parameter encryption. @param[in] AuthHash Hash algorithm to use for the session. @param[out] SessionHandle Handle for the newly created session. @param[out] NonceTPM The initial nonce from the TPM, used in the computation of the sessionKey. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2StartAuthSession ( IN TPMI_DH_OBJECT TpmKey, IN TPMI_DH_ENTITY Bind, IN TPM2B_NONCE *NonceCaller, IN TPM2B_ENCRYPTED_SECRET *Salt, IN TPM_SE SessionType, IN TPMT_SYM_DEF *Symmetric, IN TPMI_ALG_HASH AuthHash, OUT TPMI_SH_AUTH_SESSION *SessionHandle, OUT TPM2B_NONCE *NonceTPM ) { EFI_STATUS Status; TPM2_START_AUTH_SESSION_COMMAND SendBuffer; TPM2_START_AUTH_SESSION_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_StartAuthSession); SendBuffer.TpmKey = SwapBytes32 (TpmKey); SendBuffer.Bind = SwapBytes32 (Bind); Buffer = (UINT8 *)&SendBuffer.NonceCaller; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NonceCaller->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, NonceCaller->buffer, NonceCaller->size); Buffer += NonceCaller->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Salt->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, Salt->secret, Salt->size); Buffer += Salt->size; *(TPM_SE *)Buffer = SessionType; Buffer++; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->algorithm)); Buffer += sizeof(UINT16); switch (Symmetric->algorithm) { case TPM_ALG_NULL: break; case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_SYMCIPHER: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.sym)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->mode.sym)); Buffer += sizeof(UINT16); break; case TPM_ALG_XOR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Symmetric->keyBits.xor)); Buffer += sizeof(UINT16); break; default: ASSERT (FALSE); DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - Symmetric->algorithm - %x\n", Symmetric->algorithm)); return EFI_UNSUPPORTED; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (AuthHash)); Buffer += sizeof(UINT16); SendBufferSize = (UINT32) ((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2StartAuthSession - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } // // Return the response // *SessionHandle = SwapBytes32 (RecvBuffer.SessionHandle); NonceTPM->size = SwapBytes16 (RecvBuffer.NonceTPM.size); if (NonceTPM->size > sizeof(TPMU_HA)) { DEBUG ((DEBUG_ERROR, "Tpm2StartAuthSession - NonceTPM->size error %x\n", NonceTPM->size)); return EFI_DEVICE_ERROR; } CopyMem (NonceTPM->buffer, &RecvBuffer.NonceTPM.buffer, NonceTPM->size); return EFI_SUCCESS; }
/** Write some blocks to the device. @param UsbMass The USB mass storage device to write to @param Lba The start block number @param TotalBlock Total block number to write @param Buffer Pointer to the source buffer for the data. @retval EFI_SUCCESS Data are written into the buffer @retval Others Failed to write all the data **/ EFI_STATUS UsbBootWriteBlocks ( IN USB_MASS_DEVICE *UsbMass, IN UINT32 Lba, IN UINTN TotalBlock, IN UINT8 *Buffer ) { USB_BOOT_WRITE10_CMD WriteCmd; EFI_STATUS Status; UINT16 Count; UINT32 BlockSize; UINT32 ByteSize; UINT32 Timeout; BlockSize = UsbMass->BlockIoMedia.BlockSize; Status = EFI_SUCCESS; while (TotalBlock > 0) { // // Split the total blocks into smaller pieces to ease the pressure // on the device. We must split the total block because the WRITE10 // command only has 16 bit transfer length (in the unit of block). // Count = (UINT16)((TotalBlock < USB_BOOT_IO_BLOCKS) ? TotalBlock : USB_BOOT_IO_BLOCKS); ByteSize = (UINT32)Count * BlockSize; // // USB command's upper limit timeout is 5s. [USB2.0-9.2.6.1] // Timeout = (UINT32) USB_BOOT_GENERAL_CMD_TIMEOUT; // // Fill in the write10 command block // ZeroMem (&WriteCmd, sizeof (USB_BOOT_WRITE10_CMD)); WriteCmd.OpCode = USB_BOOT_WRITE10_OPCODE; WriteCmd.Lun = (UINT8) (USB_BOOT_LUN (UsbMass->Lun)); WriteUnaligned32 ((UINT32 *) WriteCmd.Lba, SwapBytes32 (Lba)); WriteUnaligned16 ((UINT16 *) WriteCmd.TransferLen, SwapBytes16 (Count)); Status = UsbBootExecCmdWithRetry ( UsbMass, &WriteCmd, (UINT8) sizeof (USB_BOOT_WRITE10_CMD), EfiUsbDataOut, Buffer, ByteSize, Timeout ); if (EFI_ERROR (Status)) { return Status; } DEBUG ((EFI_D_BLKIO, "UsbBootWriteBlocks: LBA (0x%x), Blk (0x%x)\n", Lba, Count)); Lba += Count; Buffer += Count * BlockSize; TotalBlock -= Count; } return Status; }
/** Create the Boot####, Driver####, SysPrep####, variable from the load option. @param LoadOption Pointer to the load option. @retval EFI_SUCCESS The variable was created. @retval Others Error status returned by RT->SetVariable. **/ EFI_STATUS EFIAPI EfiBootManagerLoadOptionToVariable ( IN CONST EFI_BOOT_MANAGER_LOAD_OPTION *Option ) { UINTN VariableSize; UINT8 *Variable; UINT8 *Ptr; CHAR16 OptionName[BM_OPTION_NAME_LEN]; CHAR16 *Description; CHAR16 NullChar; UINT32 VariableAttributes; if ((Option->OptionNumber == LoadOptionNumberUnassigned) || (Option->FilePath == NULL) || ((UINT32) Option->OptionType >= LoadOptionTypeMax) ) { return EFI_INVALID_PARAMETER; } // // Convert NULL description to empty description // NullChar = L'\0'; Description = Option->Description; if (Description == NULL) { Description = &NullChar; } /* UINT32 Attributes; UINT16 FilePathListLength; CHAR16 Description[]; EFI_DEVICE_PATH_PROTOCOL FilePathList[]; UINT8 OptionalData[]; TODO: FilePathList[] IS: A packed array of UEFI device paths. The first element of the array is a device path that describes the device and location of the Image for this load option. The FilePathList[0] is specific to the device type. Other device paths may optionally exist in the FilePathList, but their usage is OSV specific. Each element in the array is variable length, and ends at the device path end structure. */ VariableSize = sizeof (Option->Attributes) + sizeof (UINT16) + StrSize (Description) + GetDevicePathSize (Option->FilePath) + Option->OptionalDataSize; Variable = AllocatePool (VariableSize); ASSERT (Variable != NULL); Ptr = Variable; WriteUnaligned32 ((UINT32 *) Ptr, Option->Attributes); Ptr += sizeof (Option->Attributes); WriteUnaligned16 ((UINT16 *) Ptr, (UINT16) GetDevicePathSize (Option->FilePath)); Ptr += sizeof (UINT16); CopyMem (Ptr, Description, StrSize (Description)); Ptr += StrSize (Description); CopyMem (Ptr, Option->FilePath, GetDevicePathSize (Option->FilePath)); Ptr += GetDevicePathSize (Option->FilePath); CopyMem (Ptr, Option->OptionalData, Option->OptionalDataSize); UnicodeSPrint (OptionName, sizeof (OptionName), L"%s%04x", mBmLoadOptionName[Option->OptionType], Option->OptionNumber); VariableAttributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE; return gRT->SetVariable ( OptionName, &gEfiGlobalVariableGuid, VariableAttributes, VariableSize, Variable ); }
/** This command allows setting of the authorization policy for the platform hierarchy (platformPolicy), the storage hierarchy (ownerPolicy), and and the endorsement hierarchy (endorsementPolicy). @param[in] AuthHandle TPM_RH_ENDORSEMENT, TPM_RH_OWNER or TPM_RH_PLATFORM+{PP} parameters to be validated @param[in] AuthSession Auth Session context @param[in] AuthPolicy An authorization policy hash @param[in] HashAlg The hash algorithm to use for the policy @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2SetPrimaryPolicy ( IN TPMI_RH_HIERARCHY_AUTH AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, IN TPM2B_DIGEST *AuthPolicy, IN TPMI_ALG_HASH HashAlg ) { EFI_STATUS Status; TPM2_SET_PRIMARY_POLICY_COMMAND SendBuffer; TPM2_SET_PRIMARY_POLICY_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; UINT32 SessionInfoSize; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_SetPrimaryPolicy); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // Real data // WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(AuthPolicy->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, AuthPolicy->buffer, AuthPolicy->size); Buffer += AuthPolicy->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(HashAlg)); Buffer += sizeof(UINT16); SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2SetPrimaryPolicy - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** This command is used to set the desired PCR allocation of PCR and algorithms. @param[in] AuthHandle TPM_RH_PLATFORM+{PP} @param[in] AuthSession Auth Session context @param[in] PcrAllocation The requested allocation @param[out] AllocationSuccess YES if the allocation succeeded @param[out] MaxPCR maximum number of PCR that may be in a bank @param[out] SizeNeeded number of octets required to satisfy the request @param[out] SizeAvailable Number of octets available. Computed before the allocation @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2PcrAllocate ( IN TPMI_RH_PLATFORM AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, IN TPML_PCR_SELECTION *PcrAllocation, OUT TPMI_YES_NO *AllocationSuccess, OUT UINT32 *MaxPCR, OUT UINT32 *SizeNeeded, OUT UINT32 *SizeAvailable ) { EFI_STATUS Status; TPM2_PCR_ALLOCATE_COMMAND Cmd; TPM2_PCR_ALLOCATE_RESPONSE Res; UINT32 CmdSize; UINT32 RespSize; UINT8 *Buffer; UINT32 SessionInfoSize; UINT8 *ResultBuf; UINT32 ResultBufSize; UINTN Index; // // Construct command // Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS); Cmd.Header.paramSize = SwapBytes32(sizeof(Cmd)); Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Allocate); Cmd.AuthHandle = SwapBytes32(AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&Cmd.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; Cmd.AuthSessionSize = SwapBytes32(SessionInfoSize); // Count WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(PcrAllocation->count)); Buffer += sizeof(UINT32); for (Index = 0; Index < PcrAllocation->count; Index++) { WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(PcrAllocation->pcrSelections[Index].hash)); Buffer += sizeof(UINT16); *(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect; Buffer++; CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect); Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect; } CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd); Cmd.Header.paramSize = SwapBytes32(CmdSize); ResultBuf = (UINT8 *) &Res; ResultBufSize = sizeof(Res); // // Call the TPM // Status = Tpm2SubmitCommand ( CmdSize, (UINT8 *)&Cmd, &ResultBufSize, ResultBuf ); if (EFI_ERROR(Status)) { goto Done; } if (ResultBufSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n")); Status = EFI_BUFFER_TOO_SMALL; goto Done; } // // Validate response headers // RespSize = SwapBytes32(Res.Header.paramSize); if (RespSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize)); Status = EFI_BUFFER_TOO_SMALL; goto Done; } // // Fail if command failed // if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG((EFI_D_ERROR,"Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); Status = EFI_DEVICE_ERROR; goto Done; } // // Return the response // *AllocationSuccess = Res.AllocationSuccess; *MaxPCR = SwapBytes32(Res.MaxPCR); *SizeNeeded = SwapBytes32(Res.SizeNeeded); *SizeAvailable = SwapBytes32(Res.SizeAvailable); Done: // // Clear AuthSession Content // ZeroMem (&Cmd, sizeof(Cmd)); ZeroMem (&Res, sizeof(Res)); return Status; }
/** Reads I/O registers. @param[in] PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param[in] This Pointer to local data for the interface. @param[in] Width The width of the access. Enumerated in bytes. @param[in] Address The physical address of the access. @param[in] Count The number of accesses to perform. @param[out] Buffer A pointer to the buffer of data. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. @retval EFI_INVALID_PARAMETER Buffer is NULL. @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count is not valid for this EFI system. **/ EFI_STATUS EFIAPI CpuIoServiceRead ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_CPU_IO_PPI *This, IN EFI_PEI_CPU_IO_PPI_WIDTH Width, IN UINT64 Address, IN UINTN Count, OUT VOID *Buffer ) { EFI_STATUS Status; UINT8 InStride; UINT8 OutStride; EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth; BOOLEAN Aligned; UINT8 *Uint8Buffer; Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } // // Select loop based on the width of the transfer // InStride = mInStride[Width]; OutStride = mOutStride[Width]; OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03); // // Fifo operations supported for (mInStride[Width] == 0) // if (InStride == 0) { switch (OperationWidth) { case EfiPeiCpuIoWidthUint8: IoReadFifo8 ((UINTN)Address, Count, Buffer); return EFI_SUCCESS; case EfiPeiCpuIoWidthUint16: IoReadFifo16 ((UINTN)Address, Count, Buffer); return EFI_SUCCESS; case EfiPeiCpuIoWidthUint32: IoReadFifo32 ((UINTN)Address, Count, Buffer); return EFI_SUCCESS; default: // // The CpuIoCheckParameter call above will ensure that this // path is not taken. // ASSERT (FALSE); break; } } Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00); for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { if (OperationWidth == EfiPeiCpuIoWidthUint8) { *Uint8Buffer = IoRead8 ((UINTN)Address); } else if (OperationWidth == EfiPeiCpuIoWidthUint16) { if (Aligned) { *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address); } else { WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint32) { if (Aligned) { *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address); } else { WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address)); } } } return EFI_SUCCESS; }
/** This command is used to cause an update to the indicated PCR. The digests parameter contains one or more tagged digest value identified by an algorithm ID. For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg). @param[in] PcrHandle Handle of the PCR @param[in] Digests List of tagged digest values to be extended @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2PcrExtend ( IN TPMI_DH_PCR PcrHandle, IN TPML_DIGEST_VALUES *Digests ) { EFI_STATUS Status; TPM2_PCR_EXTEND_COMMAND Cmd; TPM2_PCR_EXTEND_RESPONSE Res; UINT32 CmdSize; UINT32 RespSize; UINT32 ResultBufSize; UINT8 *Buffer; UINTN Index; UINT32 SessionInfoSize; UINT16 DigestSize; Cmd.Header.tag = SwapBytes16(TPM_ST_SESSIONS); Cmd.Header.commandCode = SwapBytes32(TPM_CC_PCR_Extend); Cmd.PcrHandle = SwapBytes32(PcrHandle); // // Add in Auth session // Buffer = (UINT8 *)&Cmd.AuthSessionPcr; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer); Buffer += SessionInfoSize; Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize); //Digest Count WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32(Digests->count)); Buffer += sizeof(UINT32); //Digest for (Index = 0; Index < Digests->count; Index++) { WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Digests->digests[Index].hashAlg)); Buffer += sizeof(UINT16); DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg); if (DigestSize == 0) { DEBUG ((EFI_D_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg)); return EFI_DEVICE_ERROR; } CopyMem( Buffer, &Digests->digests[Index].digest, DigestSize ); Buffer += DigestSize; } CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd); Cmd.Header.paramSize = SwapBytes32(CmdSize); ResultBufSize = sizeof(Res); Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res); if (EFI_ERROR(Status)) { return Status; } if (ResultBufSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n")); return EFI_BUFFER_TOO_SMALL; } // // Validate response headers // RespSize = SwapBytes32(Res.Header.paramSize); if (RespSize > sizeof(Res)) { DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize)); return EFI_BUFFER_TOO_SMALL; } // // Fail if command failed // if (SwapBytes32(Res.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); return EFI_DEVICE_ERROR; } // // Unmarshal the response // // None return EFI_SUCCESS; }
/** Reads a range of PCI configuration registers into a caller supplied buffer. Reads the range of PCI configuration registers specified by StartAddress and Size into the buffer specified by Buffer. This function only allows the PCI configuration registers from a single PCI function to be read. Size is returned. When possible 32-bit PCI configuration read cycles are used to read from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit and 16-bit PCI configuration read cycles may be used at the beginning and the end of the range. If StartAddress > 0x0FFFFFFF, then ASSERT(). If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). If Size > 0 and Buffer is NULL, then ASSERT(). @param StartAddress The starting address that encodes the PCI Bus, Device, Function and Register. @param Size The size in bytes of the transfer. @param Buffer The pointer to a buffer receiving the data read. @return Size **/ UINTN EFIAPI PciReadBuffer ( IN UINTN StartAddress, IN UINTN Size, OUT VOID *Buffer ) { UINTN ReturnValue; ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); if (Size == 0) { return Size; } ASSERT (Buffer != NULL); // // Save Size for return // ReturnValue = Size; if ((StartAddress & BIT0) != 0) { // // Read a byte if StartAddress is byte aligned // *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); StartAddress += sizeof (UINT8); Size -= sizeof (UINT8); Buffer = (UINT8*)Buffer + 1; } if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { // // Read a word if StartAddress is word aligned // WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); StartAddress += sizeof (UINT16); Size -= sizeof (UINT16); Buffer = (UINT16*)Buffer + 1; } while (Size >= sizeof (UINT32)) { // // Read as many double words as possible // WriteUnaligned32 (Buffer, PciRead32 (StartAddress)); StartAddress += sizeof (UINT32); Size -= sizeof (UINT32); Buffer = (UINT32*)Buffer + 1; } if (Size >= sizeof (UINT16)) { // // Read the last remaining word if exist // WriteUnaligned16 (Buffer, PciRead16 (StartAddress)); StartAddress += sizeof (UINT16); Size -= sizeof (UINT16); Buffer = (UINT16*)Buffer + 1; } if (Size >= sizeof (UINT8)) { // // Read the last remaining byte if exist // *(volatile UINT8 *)Buffer = PciRead8 (StartAddress); } return ReturnValue; }
/** This command is used to check to see if specific combinations of algorithm parameters are supported. @param[in] Parameters Algorithm parameters to be validated @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2TestParms ( IN TPMT_PUBLIC_PARMS *Parameters ) { EFI_STATUS Status; TPM2_TEST_PARMS_COMMAND SendBuffer; TPM2_TEST_PARMS_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT8 *Buffer; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_TestParms); Buffer = (UINT8 *)&SendBuffer.Parameters; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->type)); Buffer += sizeof(UINT16); switch (Parameters->type) { case TPM_ALG_KEYEDHASH: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.keyedHashDetail.scheme.scheme) { case TPM_ALG_HMAC: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.hmac.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_XOR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.hashAlg)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.keyedHashDetail.scheme.details.xor.kdf)); Buffer += sizeof(UINT16); break; default: return EFI_INVALID_PARAMETER; } case TPM_ALG_SYMCIPHER: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.algorithm)); Buffer += sizeof(UINT16); switch (Parameters->parameters.symDetail.algorithm) { case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_XOR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.symDetail.keyBits.xor)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } break; case TPM_ALG_RSA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.algorithm)); Buffer += sizeof(UINT16); switch (Parameters->parameters.rsaDetail.symmetric.algorithm) { case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.symmetric.mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.rsaDetail.scheme.scheme) { case TPM_ALG_RSASSA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsassa.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_RSAPSS: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.rsapss.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_RSAES: break; case TPM_ALG_OAEP: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.scheme.details.oaep.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.rsaDetail.keyBits)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Parameters->parameters.rsaDetail.exponent)); Buffer += sizeof(UINT32); break; case TPM_ALG_ECC: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.algorithm)); Buffer += sizeof(UINT16); switch (Parameters->parameters.eccDetail.symmetric.algorithm) { case TPM_ALG_AES: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.aes)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.aes)); Buffer += sizeof(UINT16); break; case TPM_ALG_SM4: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.keyBits.SM4)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.symmetric.mode.SM4)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.eccDetail.scheme.scheme) { case TPM_ALG_ECDSA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdsa.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_ECDAA: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecdaa.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_ECSCHNORR: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.scheme.details.ecSchnorr.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_ECDH: break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.curveID)); Buffer += sizeof(UINT16); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.scheme)); Buffer += sizeof(UINT16); switch (Parameters->parameters.eccDetail.kdf.scheme) { case TPM_ALG_MGF1: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.mgf1.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_KDF1_SP800_108: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_sp800_108.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_KDF1_SP800_56a: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf1_SP800_56a.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_KDF2: WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Parameters->parameters.eccDetail.kdf.details.kdf2.hashAlg)); Buffer += sizeof(UINT16); break; case TPM_ALG_NULL: break; default: return EFI_INVALID_PARAMETER; } break; default: return EFI_INVALID_PARAMETER; } SendBufferSize = (UINT32)((UINTN)Buffer - (UINTN)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2TestParms - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } if (SwapBytes32(RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2TestParms - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); return EFI_UNSUPPORTED; } return EFI_SUCCESS; }
/** Get file name from device path. The file name may contain one or more device path node. Save the file name in a buffer if file name is found. The caller is responsible to free the buffer. @param[in] DevicePath A pointer to a device path. @param[out] FileName The callee allocated buffer to save the file name if file name is found. @param[out] FileNameOffset The offset of file name in device path if file name is found. @retval UINTN The file name length. 0 means file name is not found. **/ UINTN GetFileName ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT UINT8 **FileName, OUT UINTN *FileNameOffset ) { UINTN Length; EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; EFI_DEVICE_PATH_PROTOCOL *RootDevicePath; CHAR8 *NodeStr; UINTN NodeStrLength; CHAR16 LastNodeChar; CHAR16 FirstNodeChar; // // Get the length of DevicePath before file name. // Length = 0; RootDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; while (!IsDevicePathEnd (RootDevicePath)) { if ((DevicePathType(RootDevicePath) == MEDIA_DEVICE_PATH) && (DevicePathSubType(RootDevicePath) == MEDIA_FILEPATH_DP)) { break; } Length += DevicePathNodeLength (RootDevicePath); RootDevicePath = NextDevicePathNode (RootDevicePath); } *FileNameOffset = Length; if (Length == 0) { return 0; } // // Get the file name length. // Length = 0; TmpDevicePath = RootDevicePath; while (!IsDevicePathEnd (TmpDevicePath)) { if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) { break; } Length += DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL); TmpDevicePath = NextDevicePathNode (TmpDevicePath); } if (Length == 0) { return 0; } *FileName = AllocateZeroPool (Length); ASSERT (*FileName != NULL); // // Copy the file name to the buffer. // Length = 0; LastNodeChar = '\\'; TmpDevicePath = RootDevicePath; while (!IsDevicePathEnd (TmpDevicePath)) { if ((DevicePathType(TmpDevicePath) != MEDIA_DEVICE_PATH) || (DevicePathSubType(TmpDevicePath) != MEDIA_FILEPATH_DP)) { break; } FirstNodeChar = (CHAR16) ReadUnaligned16 ((UINT16 *)((UINT8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL))); NodeStr = (CHAR8 *)TmpDevicePath + sizeof (EFI_DEVICE_PATH_PROTOCOL); NodeStrLength = DevicePathNodeLength (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL) - sizeof(CHAR16); if ((FirstNodeChar == '\\') && (LastNodeChar == '\\')) { // // Skip separator "\" when there are two separators. // NodeStr += sizeof (CHAR16); NodeStrLength -= sizeof (CHAR16); } else if ((FirstNodeChar != '\\') && (LastNodeChar != '\\')) { // // Add separator "\" when there is no separator. // WriteUnaligned16 ((UINT16 *)(*FileName + Length), '\\'); Length += sizeof (CHAR16); } CopyMem (*FileName + Length, NodeStr, NodeStrLength); Length += NodeStrLength; LastNodeChar = (CHAR16) ReadUnaligned16 ((UINT16 *) (NodeStr + NodeStrLength - sizeof(CHAR16))); TmpDevicePath = NextDevicePathNode (TmpDevicePath); } return Length; }
STATIC EFI_STATUS BootOptionSetFields ( IN BDS_LOAD_OPTION* BootOption, IN UINT32 Attributes, IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, IN ARM_BDS_LOADER_TYPE BootType, IN UINT8* OptionalData, IN UINTN OptionalDataSize ) { EFI_LOAD_OPTION EfiLoadOption; UINTN EfiLoadOptionSize; UINTN BootDescriptionSize; UINT16 FilePathListLength; UINT8* EfiLoadOptionPtr; UINT8* InitrdPathListPtr; ARM_BDS_LINUX_ARGUMENTS* DestLinuxArguments; ARM_BDS_LINUX_ARGUMENTS* SrcLinuxArguments; ARM_BDS_LOADER_ARGUMENTS* BootArguments; // If we are overwriting an existent Boot Option then we have to free previously allocated memory if (BootOption->LoadOption) { FreePool (BootOption->LoadOption); } BootDescriptionSize = StrSize (BootDescription); // Fixup the size in case of entry specific to ArmPlatformPkg/Bds if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { OptionalDataSize += sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER); } // Compute the size of the FilePath list FilePathListLength = GetUnalignedDevicePathSize (DevicePath); // Allocate the memory for the EFI Load Option EfiLoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + BootDescriptionSize + FilePathListLength + OptionalDataSize; EfiLoadOption = (EFI_LOAD_OPTION)AllocatePool(EfiLoadOptionSize); EfiLoadOptionPtr = EfiLoadOption; // // Populate the EFI Load Option and BDS Boot Option structures // // Attributes fields BootOption->Attributes = Attributes; *(UINT32*)EfiLoadOptionPtr = Attributes; EfiLoadOptionPtr += sizeof(UINT32); // FilePath List fields BootOption->FilePathListLength = FilePathListLength; *(UINT16*)EfiLoadOptionPtr = FilePathListLength; EfiLoadOptionPtr += sizeof(UINT16); // Boot description fields BootOption->Description = (CHAR16*)EfiLoadOptionPtr; CopyMem (EfiLoadOptionPtr, BootDescription, BootDescriptionSize); EfiLoadOptionPtr += BootDescriptionSize; // File path fields BootOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)EfiLoadOptionPtr; CopyMem (EfiLoadOptionPtr, DevicePath, FilePathListLength); EfiLoadOptionPtr += FilePathListLength; // Optional Data fields, Do unaligned writes BootOption->OptionalData = EfiLoadOptionPtr; if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { // Write the header WriteUnaligned32 ((UINT32 *)EfiLoadOptionPtr, ARM_BDS_OPTIONAL_DATA_SIGNATURE); WriteUnaligned32 ((UINT32 *)(EfiLoadOptionPtr + 4), BootType); // OptionalData should have been initialized by the caller of this function ASSERT (OptionalData != NULL); BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)OptionalData; SrcLinuxArguments = &(BootArguments->LinuxArguments); DestLinuxArguments = &((ARM_BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments.LinuxArguments; WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->CmdLineSize), SrcLinuxArguments->CmdLineSize); WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->InitrdSize), SrcLinuxArguments->InitrdSize); if (SrcLinuxArguments->CmdLineSize > 0) { CopyMem ((VOID*)(DestLinuxArguments + 1), (VOID*)(SrcLinuxArguments + 1), SrcLinuxArguments->CmdLineSize); } if (SrcLinuxArguments->InitrdSize > 0) { InitrdPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize); CopyMem (InitrdPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize), SrcLinuxArguments->InitrdSize); } } else { if (OptionalData != NULL) { CopyMem (BootOption->OptionalData, OptionalData, OptionalDataSize); } } BootOption->OptionalDataSize = OptionalDataSize; // If this function is called at the creation of the Boot Device entry (not at the update) the // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry if (BootOption->LoadOptionSize == 0) { BootOption->LoadOptionIndex = BootOptionAllocateBootIndex (); } // Fill the EFI Load option fields BootOption->LoadOption = EfiLoadOption; BootOption->LoadOptionSize = EfiLoadOptionSize; return EFI_SUCCESS; }