/** Writes 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[in] 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 CpuMemoryServiceWrite ( 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, IN 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) { MmioWrite8 ((UINTN)Address, *Uint8Buffer); } else if (OperationWidth == EfiPeiCpuIoWidthUint16) { if (Aligned) { MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); } else { MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint32) { if (Aligned) { MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); } else { MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint64) { if (Aligned) { MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); } else { MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer)); } } } return EFI_SUCCESS; }
/** Check whether the device path node is ISA Serial Node. @param Acpi Device path node to be checked @retval TRUE It's ISA Serial Node. @retval FALSE It's NOT ISA Serial Node. **/ BOOLEAN IsIsaSerialNode ( IN ACPI_HID_DEVICE_PATH *Acpi ) { return (BOOLEAN) ( (DevicePathType (Acpi) == ACPI_DEVICE_PATH) && (DevicePathSubType (Acpi) == ACPI_DP) && (ReadUnaligned32 (&Acpi->HID) == EISA_PNP_ID (0x0501)) ); }
/** Check to see if this driver supports the given controller @param This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param Controller The handle of the controller to test. @param RemainingDevicePath A pointer to the remaining portion of a device path. @return EFI_SUCCESS This driver can support the given controller **/ EFI_STATUS EFIAPI SerialControllerDriverSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; UART_DEVICE_PATH *Uart; UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; // // Test RemainingDevicePath // if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) { Status = EFI_UNSUPPORTED; Uart = SkipControllerDevicePathNode (RemainingDevicePath, NULL, NULL); if (DevicePathType (Uart) != MESSAGING_DEVICE_PATH || DevicePathSubType (Uart) != MSG_UART_DP || DevicePathNodeLength (Uart) != sizeof (UART_DEVICE_PATH) ) { return EFI_UNSUPPORTED; } // // Do a rough check because Clock Rate is unknown until DriverBindingStart() // if (!VerifyUartParameters (0, Uart->BaudRate, Uart->DataBits, Uart->Parity, Uart->StopBits, NULL, NULL)) { return EFI_UNSUPPORTED; } FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); if (IsUartFlowControlDevicePathNode (FlowControl)) { // // If the second node is Flow Control Node, // return error when it request other than hardware flow control. // if ((ReadUnaligned32 (&FlowControl->FlowControlMap) & ~UART_FLOW_CONTROL_HARDWARE) != 0) { return EFI_UNSUPPORTED; } } } Status = IsSioSerialController (Controller); if (EFI_ERROR (Status)) { Status = IsPciSerialController (Controller); } return Status; }
/** Returns the size of a given image execution info table in bytes. This function returns the size, in bytes, of the image execution info table specified by ImageExeInfoTable. If ImageExeInfoTable is NULL, then 0 is returned. @param ImageExeInfoTable A pointer to a image execution info table structure. @retval 0 If ImageExeInfoTable is NULL. @retval Others The size of a image execution info table in bytes. **/ UINTN GetImageExeInfoTableSize ( EFI_IMAGE_EXECUTION_INFO_TABLE *ImageExeInfoTable ) { UINTN Index; EFI_IMAGE_EXECUTION_INFO *ImageExeInfoItem; UINTN TotalSize; if (ImageExeInfoTable == NULL) { return 0; } ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoTable + sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE)); TotalSize = sizeof (EFI_IMAGE_EXECUTION_INFO_TABLE); for (Index = 0; Index < ImageExeInfoTable->NumberOfImages; Index++) { TotalSize += ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize); ImageExeInfoItem = (EFI_IMAGE_EXECUTION_INFO *) ((UINT8 *) ImageExeInfoItem + ReadUnaligned32 ((UINT32 *) &ImageExeInfoItem->InfoSize)); } return TotalSize; }
VOID ArmPlatformGetGlobalVariable ( IN UINTN VariableOffset, IN UINTN VariableSize, OUT VOID* Variable ) { UINTN GlobalVariableBase; // Ensure the Global Variable Size have been initialized ASSERT (VariableOffset < PcdGet32 (PcdSecGlobalVariableSize)); GlobalVariableBase = PcdGet32 (PcdCPUCoresSecStackBase) + PcdGet32 (PcdCPUCoreSecPrimaryStackSize) - PcdGet32 (PcdSecGlobalVariableSize); if (VariableSize == 4) { *(UINT32*)Variable = ReadUnaligned32 ((CONST UINT32*)(GlobalVariableBase + VariableOffset)); } else if (VariableSize == 8) { *(UINT64*)Variable = ReadUnaligned64 ((CONST UINT64*)(GlobalVariableBase + VariableOffset)); } else { CopyMem (Variable, (VOID*)(GlobalVariableBase + VariableOffset), VariableSize); } }
/** Worker function that displays the list of boot options that is passed in. The function loops over the entries of the list of boot options that is passed in. For each entry, the boot option description is displayed on a single line along with the position of the option in the list. In debug mode, the UEFI device path and the arguments of the boot option are displayed as well in subsequent lines. @param[in] BootOptionsList List of the boot options **/ STATIC VOID DisplayBootOptions ( IN LIST_ENTRY* BootOptionsList ) { EFI_STATUS Status; UINTN BootOptionCount; LIST_ENTRY *Entry; BDS_LOAD_OPTION *BdsLoadOption; BOOLEAN IsUnicode; BootOptionCount = 0 ; for (Entry = GetFirstNode (BootOptionsList); !IsNull (BootOptionsList, Entry); Entry = GetNextNode (BootOptionsList, Entry) ) { BdsLoadOption = LOAD_OPTION_FROM_LINK (Entry); Print (L"[%d] %s\n", ++BootOptionCount, BdsLoadOption->Description); DEBUG_CODE_BEGIN (); CHAR16* DevicePathTxt; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; ARM_BDS_LOADER_TYPE LoaderType; ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; Status = gBS->LocateProtocol ( &gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol ); ASSERT_EFI_ERROR (Status); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( BdsLoadOption->FilePathList, TRUE, TRUE ); Print (L"\t- %s\n", DevicePathTxt); OptionalData = BdsLoadOption->OptionalData; if (IS_ARM_BDS_BOOTENTRY (BdsLoadOption)) { LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT ) ) { Print (L"\t- Arguments: %a\n", &OptionalData->Arguments.LinuxArguments + 1); } } else if (OptionalData != NULL) { if (IsPrintableString (OptionalData, &IsUnicode)) { if (IsUnicode) { Print (L"\t- Arguments: %s\n", OptionalData); } else { AsciiPrint ("\t- Arguments: %a\n", OptionalData); } } } FreePool (DevicePathTxt); DEBUG_CODE_END (); } }
/** Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function only supports blocking execution of the command. @param[in] Private The pointer to the NVME_CONTEXT Data structure. @param[in] NamespaceId Is a 32 bit Namespace ID to which the Express HCI command packet will be sent. A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace ID specifies that the command packet should be sent to all valid namespaces. @param[in,out] Packet A pointer to the EDKII PEI NVM Express PassThru Command Packet to send to the NVMe namespace specified by NamespaceId. @retval EFI_SUCCESS The EDKII PEI NVM Express Command Packet was sent by the host. TransferLength bytes were transferred to, or from DataBuffer. @retval EFI_NOT_READY The EDKII PEI NVM Express Command Packet could not be sent because the controller is not ready. The caller may retry again later. @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the EDKII PEI NVM Express Command Packet. @retval EFI_INVALID_PARAMETER Namespace, or the contents of EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The EDKII PEI NVM Express Command Packet was not sent, so no additional status information is available. @retval EFI_UNSUPPORTED The command described by the EDKII PEI NVM Express Command Packet is not supported by the host adapter. The EDKII PEI NVM Express Command Packet was not sent, so no additional status information is available. @retval EFI_TIMEOUT A timeout occurred while waiting for the EDKII PEI NVM Express Command Packet to execute. **/ EFI_STATUS NvmePassThru ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private, IN UINT32 NamespaceId, IN OUT EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet ) { EFI_STATUS Status; NVME_SQ *Sq; NVME_CQ *Cq; UINT8 QueueId; UINTN SqSize; UINTN CqSize; EDKII_IOMMU_OPERATION MapOp; UINTN MapLength; EFI_PHYSICAL_ADDRESS PhyAddr; VOID *MapData; VOID *MapMeta; UINT32 Bytes; UINT32 Offset; UINT32 Data32; UINT64 Timer; // // Check the data fields in Packet parameter // if (Packet == NULL) { DEBUG (( DEBUG_ERROR, "%a, Invalid parameter: Packet(%lx)\n", __FUNCTION__, (UINTN)Packet )); return EFI_INVALID_PARAMETER; } if ((Packet->NvmeCmd == NULL) || (Packet->NvmeCompletion == NULL)) { DEBUG (( DEBUG_ERROR, "%a, Invalid parameter: NvmeCmd (%lx)/NvmeCompletion(%lx)\n", __FUNCTION__, (UINTN)Packet->NvmeCmd, (UINTN)Packet->NvmeCompletion )); return EFI_INVALID_PARAMETER; } if (Packet->QueueType != NVME_ADMIN_QUEUE && Packet->QueueType != NVME_IO_QUEUE) { DEBUG (( DEBUG_ERROR, "%a, Invalid parameter: QueueId(%lx)\n", __FUNCTION__, (UINTN)Packet->QueueType )); return EFI_INVALID_PARAMETER; } QueueId = Packet->QueueType; Sq = Private->SqBuffer[QueueId] + Private->SqTdbl[QueueId].Sqt; Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; if (QueueId == NVME_ADMIN_QUEUE) { SqSize = NVME_ASQ_SIZE + 1; CqSize = NVME_ACQ_SIZE + 1; } else { SqSize = NVME_CSQ_SIZE + 1; CqSize = NVME_CCQ_SIZE + 1; } if (Packet->NvmeCmd->Nsid != NamespaceId) { DEBUG (( DEBUG_ERROR, "%a: Nsid mismatch (%x, %x)\n", __FUNCTION__, Packet->NvmeCmd->Nsid, NamespaceId )); return EFI_INVALID_PARAMETER; } ZeroMem (Sq, sizeof (NVME_SQ)); Sq->Opc = Packet->NvmeCmd->Cdw0.Opcode; Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation; Sq->Cid = Packet->NvmeCmd->Cdw0.Cid; Sq->Nsid = Packet->NvmeCmd->Nsid; // // Currently we only support PRP for data transfer, SGL is NOT supported // ASSERT (Sq->Psdt == 0); if (Sq->Psdt != 0) { DEBUG ((DEBUG_ERROR, "%a: Does not support SGL mechanism.\n", __FUNCTION__)); return EFI_UNSUPPORTED; } Sq->Prp[0] = (UINT64)(UINTN)Packet->TransferBuffer; Sq->Prp[1] = 0; MapData = NULL; MapMeta = NULL; Status = EFI_SUCCESS; // // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller // specific addresses. // if ((Sq->Opc & (BIT0 | BIT1)) != 0) { if (((Packet->TransferLength != 0) && (Packet->TransferBuffer == NULL)) || ((Packet->TransferLength == 0) && (Packet->TransferBuffer != NULL))) { return EFI_INVALID_PARAMETER; } // // Currently, we only support creating IO submission/completion queues that are // allocated internally by the driver. // if ((Packet->QueueType == NVME_ADMIN_QUEUE) && ((Sq->Opc == NVME_ADMIN_CRIOCQ_CMD) || (Sq->Opc == NVME_ADMIN_CRIOSQ_CMD))) { if ((Packet->TransferBuffer != Private->SqBuffer[NVME_IO_QUEUE]) && (Packet->TransferBuffer != Private->CqBuffer[NVME_IO_QUEUE])) { DEBUG (( DEBUG_ERROR, "%a: Does not support external IO queues creation request.\n", __FUNCTION__ )); return EFI_UNSUPPORTED; } } else { if ((Sq->Opc & BIT0) != 0) { MapOp = EdkiiIoMmuOperationBusMasterRead; } else { MapOp = EdkiiIoMmuOperationBusMasterWrite; } if ((Packet->TransferLength != 0) && (Packet->TransferBuffer != NULL)) { MapLength = Packet->TransferLength; Status = IoMmuMap ( MapOp, Packet->TransferBuffer, &MapLength, &PhyAddr, &MapData ); if (EFI_ERROR (Status) || (MapLength != Packet->TransferLength)) { Status = EFI_OUT_OF_RESOURCES; DEBUG ((DEBUG_ERROR, "%a: Fail to map data buffer.\n", __FUNCTION__)); goto Exit; } Sq->Prp[0] = PhyAddr; } if((Packet->MetadataLength != 0) && (Packet->MetadataBuffer != NULL)) { MapLength = Packet->MetadataLength; Status = IoMmuMap ( MapOp, Packet->MetadataBuffer, &MapLength, &PhyAddr, &MapMeta ); if (EFI_ERROR (Status) || (MapLength != Packet->MetadataLength)) { Status = EFI_OUT_OF_RESOURCES; DEBUG ((DEBUG_ERROR, "%a: Fail to map meta data buffer.\n", __FUNCTION__)); goto Exit; } Sq->Mptr = PhyAddr; } } } // // If the Buffer Size spans more than two memory pages (page Size as defined in CC.Mps), // then build a PRP list in the second PRP submission queue entry. // Offset = ((UINT32)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1); Bytes = Packet->TransferLength; if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) { // // Create PrpList for remaining Data Buffer. // PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); Sq->Prp[1] = NvmeCreatePrpList ( Private, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1 ); if (Sq->Prp[1] == 0) { Status = EFI_OUT_OF_RESOURCES; DEBUG ((DEBUG_ERROR, "%a: Create PRP list fail, Status - %r\n", __FUNCTION__, Status)); goto Exit; } } else if ((Offset + Bytes) > EFI_PAGE_SIZE) { Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); } if (Packet->NvmeCmd->Flags & CDW10_VALID) { Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10; } if (Packet->NvmeCmd->Flags & CDW11_VALID) { Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11; } if (Packet->NvmeCmd->Flags & CDW12_VALID) { Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12; } if (Packet->NvmeCmd->Flags & CDW13_VALID) { Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13; } if (Packet->NvmeCmd->Flags & CDW14_VALID) { Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14; } if (Packet->NvmeCmd->Flags & CDW15_VALID) { Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15; } // // Ring the submission queue doorbell. // Private->SqTdbl[QueueId].Sqt++; if (Private->SqTdbl[QueueId].Sqt == SqSize) { Private->SqTdbl[QueueId].Sqt = 0; } Data32 = ReadUnaligned32 ((UINT32 *)&Private->SqTdbl[QueueId]); Status = NVME_SET_SQTDBL (Private, QueueId, &Data32); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: NVME_SET_SQTDBL fail, Status - %r\n", __FUNCTION__, Status)); goto Exit; } // // Wait for completion queue to get filled in. // Status = EFI_TIMEOUT; Timer = 0; while (Timer < Packet->CommandTimeout) { if (Cq->Pt != Private->Pt[QueueId]) { Status = EFI_SUCCESS; break; } MicroSecondDelay (NVME_POLL_INTERVAL); Timer += NVME_POLL_INTERVAL; } if (Status == EFI_TIMEOUT) { // // Timeout occurs for an NVMe command, reset the controller to abort the outstanding command // DEBUG ((DEBUG_ERROR, "%a: Timeout occurs for the PassThru command.\n", __FUNCTION__)); Status = NvmeControllerInit (Private); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; } else { // // Return EFI_TIMEOUT to indicate a timeout occurs for PassThru command // Status = EFI_TIMEOUT; } goto Exit; } // // Move forward the Completion Queue head // Private->CqHdbl[QueueId].Cqh++; if (Private->CqHdbl[QueueId].Cqh == CqSize) { Private->CqHdbl[QueueId].Cqh = 0; Private->Pt[QueueId] ^= 1; } // // Copy the Respose Queue entry for this command to the callers response buffer // CopyMem (Packet->NvmeCompletion, Cq, sizeof (EDKII_PEI_NVM_EXPRESS_COMPLETION)); // // Check the NVMe cmd execution result // Status = NvmeCheckCqStatus (Cq); NVME_SET_CQHDBL (Private, QueueId, &Private->CqHdbl[QueueId]); Exit: if (MapMeta != NULL) { IoMmuUnmap (MapMeta); } if (MapData != NULL) { IoMmuUnmap (MapData); } return Status; }
/** Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, and the non-blocking I/O functionality is optional. @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. @param[in] NamespaceId A 32 bit namespace ID as defined in the NVMe specification to which the NVM Express Command Packet will be sent. A value of 0 denotes the NVM Express controller, a value of all 0xFF's (all bytes are 0xFF) in the namespace ID specifies that the command packet should be sent to all valid namespaces. @param[in,out] Packet A pointer to the NVM Express Command Packet. @param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking I/O is performed. If Event is NULL, then blocking I/O is performed. If Event is not NULL and non-blocking I/O is supported, then non-blocking I/O is performed, and Event will be signaled when the NVM Express Command Packet completes. @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred to, or from DataBuffer. @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred is returned in TransferLength. @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller may retry again later. @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet. @retval EFI_INVALID_PARAMETER NamespaceId or the contents of EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM Express Command Packet was not sent, so no additional status information is available. @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the NVM Express controller. The NVM Express Command Packet was not sent so no additional status information is available. @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute. **/ EFI_STATUS EFIAPI NvmExpressPassThru ( IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, IN UINT32 NamespaceId, IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet, IN EFI_EVENT Event OPTIONAL ) { NVME_CONTROLLER_PRIVATE_DATA *Private; EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; NVME_SQ *Sq; NVME_CQ *Cq; UINT16 QueueId; UINT32 Bytes; UINT16 Offset; EFI_EVENT TimerEvent; EFI_PCI_IO_PROTOCOL_OPERATION Flag; EFI_PHYSICAL_ADDRESS PhyAddr; VOID *MapData; VOID *MapMeta; VOID *MapPrpList; UINTN MapLength; UINT64 *Prp; VOID *PrpListHost; UINTN PrpListNo; UINT32 Attributes; UINT32 IoAlign; UINT32 MaxTransLen; UINT32 Data; NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; EFI_TPL OldTpl; // // check the data fields in Packet parameter. // if ((This == NULL) || (Packet == NULL)) { return EFI_INVALID_PARAMETER; } if ((Packet->NvmeCmd == NULL) || (Packet->NvmeCompletion == NULL)) { return EFI_INVALID_PARAMETER; } if (Packet->QueueType != NVME_ADMIN_QUEUE && Packet->QueueType != NVME_IO_QUEUE) { return EFI_INVALID_PARAMETER; } // // 'Attributes' with neither EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL nor // EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL set is an illegal // configuration. // Attributes = This->Mode->Attributes; if ((Attributes & (EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL)) == 0) { return EFI_INVALID_PARAMETER; } // // Buffer alignment check for TransferBuffer & MetadataBuffer. // IoAlign = This->Mode->IoAlign; if (IoAlign > 0 && (((UINTN) Packet->TransferBuffer & (IoAlign - 1)) != 0)) { return EFI_INVALID_PARAMETER; } if (IoAlign > 0 && (((UINTN) Packet->MetadataBuffer & (IoAlign - 1)) != 0)) { return EFI_INVALID_PARAMETER; } Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This); // // Check NamespaceId is valid or not. // if ((NamespaceId > Private->ControllerData->Nn) && (NamespaceId != (UINT32) -1)) { return EFI_INVALID_PARAMETER; } // // Check whether TransferLength exceeds the maximum data transfer size. // if (Private->ControllerData->Mdts != 0) { MaxTransLen = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)); if (Packet->TransferLength > MaxTransLen) { Packet->TransferLength = MaxTransLen; return EFI_BAD_BUFFER_SIZE; } } PciIo = Private->PciIo; MapData = NULL; MapMeta = NULL; MapPrpList = NULL; PrpListHost = NULL; PrpListNo = 0; Prp = NULL; TimerEvent = NULL; Status = EFI_SUCCESS; if (Packet->QueueType == NVME_ADMIN_QUEUE) { QueueId = 0; } else { if (Event == NULL) { QueueId = 1; } else { QueueId = 2; // // Submission queue full check. // if ((Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1) == Private->AsyncSqHead) { return EFI_NOT_READY; } } } Sq = Private->SqBuffer[QueueId] + Private->SqTdbl[QueueId].Sqt; Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; if (Packet->NvmeCmd->Nsid != NamespaceId) { return EFI_INVALID_PARAMETER; } ZeroMem (Sq, sizeof (NVME_SQ)); Sq->Opc = (UINT8)Packet->NvmeCmd->Cdw0.Opcode; Sq->Fuse = (UINT8)Packet->NvmeCmd->Cdw0.FusedOperation; Sq->Cid = Private->Cid[QueueId]++; Sq->Nsid = Packet->NvmeCmd->Nsid; // // Currently we only support PRP for data transfer, SGL is NOT supported. // ASSERT (Sq->Psdt == 0); if (Sq->Psdt != 0) { DEBUG ((EFI_D_ERROR, "NvmExpressPassThru: doesn't support SGL mechanism\n")); return EFI_UNSUPPORTED; } Sq->Prp[0] = (UINT64)(UINTN)Packet->TransferBuffer; // // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller specific addresses. // Note here we don't handle data buffer for CreateIOSubmitionQueue and CreateIOCompletionQueue cmds because // these two cmds are special which requires their data buffer must support simultaneous access by both the // processor and a PCI Bus Master. It's caller's responsbility to ensure this. // if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_CMD) && (Sq->Opc != NVME_ADMIN_CRIOSQ_CMD)) { if ((Packet->TransferLength == 0) || (Packet->TransferBuffer == NULL)) { return EFI_INVALID_PARAMETER; } if ((Sq->Opc & BIT0) != 0) { Flag = EfiPciIoOperationBusMasterRead; } else { Flag = EfiPciIoOperationBusMasterWrite; } MapLength = Packet->TransferLength; Status = PciIo->Map ( PciIo, Flag, Packet->TransferBuffer, &MapLength, &PhyAddr, &MapData ); if (EFI_ERROR (Status) || (Packet->TransferLength != MapLength)) { return EFI_OUT_OF_RESOURCES; } Sq->Prp[0] = PhyAddr; Sq->Prp[1] = 0; if((Packet->MetadataLength != 0) && (Packet->MetadataBuffer != NULL)) { MapLength = Packet->MetadataLength; Status = PciIo->Map ( PciIo, Flag, Packet->MetadataBuffer, &MapLength, &PhyAddr, &MapMeta ); if (EFI_ERROR (Status) || (Packet->MetadataLength != MapLength)) { PciIo->Unmap ( PciIo, MapData ); return EFI_OUT_OF_RESOURCES; } Sq->Mptr = PhyAddr; } } // // If the buffer size spans more than two memory pages (page size as defined in CC.Mps), // then build a PRP list in the second PRP submission queue entry. // Offset = ((UINT16)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1); Bytes = Packet->TransferLength; if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) { // // Create PrpList for remaining data buffer. // PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); Prp = NvmeCreatePrpList (PciIo, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo, &MapPrpList); if (Prp == NULL) { goto EXIT; } Sq->Prp[1] = (UINT64)(UINTN)Prp; } else if ((Offset + Bytes) > EFI_PAGE_SIZE) { Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); } if(Packet->NvmeCmd->Flags & CDW2_VALID) { Sq->Rsvd2 = (UINT64)Packet->NvmeCmd->Cdw2; } if(Packet->NvmeCmd->Flags & CDW3_VALID) { Sq->Rsvd2 |= LShiftU64 ((UINT64)Packet->NvmeCmd->Cdw3, 32); } if(Packet->NvmeCmd->Flags & CDW10_VALID) { Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10; } if(Packet->NvmeCmd->Flags & CDW11_VALID) { Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11; } if(Packet->NvmeCmd->Flags & CDW12_VALID) { Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12; } if(Packet->NvmeCmd->Flags & CDW13_VALID) { Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13; } if(Packet->NvmeCmd->Flags & CDW14_VALID) { Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14; } if(Packet->NvmeCmd->Flags & CDW15_VALID) { Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15; } // // Ring the submission queue doorbell. // if ((Event != NULL) && (QueueId != 0)) { Private->SqTdbl[QueueId].Sqt = (Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1); } else { Private->SqTdbl[QueueId].Sqt ^= 1; } Data = ReadUnaligned32 ((UINT32*)&Private->SqTdbl[QueueId]); Status = PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint32, NVME_BAR, NVME_SQTDBL_OFFSET(QueueId, Private->Cap.Dstrd), 1, &Data ); if (EFI_ERROR (Status)) { goto EXIT; } // // For non-blocking requests, return directly if the command is placed // in the submission queue. // if ((Event != NULL) && (QueueId != 0)) { AsyncRequest = AllocateZeroPool (sizeof (NVME_PASS_THRU_ASYNC_REQ)); if (AsyncRequest == NULL) { Status = EFI_DEVICE_ERROR; goto EXIT; } AsyncRequest->Signature = NVME_PASS_THRU_ASYNC_REQ_SIG; AsyncRequest->Packet = Packet; AsyncRequest->CommandId = Sq->Cid; AsyncRequest->CallerEvent = Event; AsyncRequest->MapData = MapData; AsyncRequest->MapMeta = MapMeta; AsyncRequest->MapPrpList = MapPrpList; AsyncRequest->PrpListNo = PrpListNo; AsyncRequest->PrpListHost = PrpListHost; OldTpl = gBS->RaiseTPL (TPL_NOTIFY); InsertTailList (&Private->AsyncPassThruQueue, &AsyncRequest->Link); gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; } Status = gBS->CreateEvent ( EVT_TIMER, TPL_CALLBACK, NULL, NULL, &TimerEvent ); if (EFI_ERROR (Status)) { goto EXIT; } Status = gBS->SetTimer(TimerEvent, TimerRelative, Packet->CommandTimeout); if (EFI_ERROR(Status)) { goto EXIT; } // // Wait for completion queue to get filled in. // Status = EFI_TIMEOUT; while (EFI_ERROR (gBS->CheckEvent (TimerEvent))) { if (Cq->Pt != Private->Pt[QueueId]) { Status = EFI_SUCCESS; break; } } // // Check the NVMe cmd execution result // if (Status != EFI_TIMEOUT) { if ((Cq->Sct == 0) && (Cq->Sc == 0)) { Status = EFI_SUCCESS; } else { Status = EFI_DEVICE_ERROR; // // Copy the Respose Queue entry for this command to the callers response buffer // CopyMem(Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION)); // // Dump every completion entry status for debugging. // DEBUG_CODE_BEGIN(); NvmeDumpStatus(Cq); DEBUG_CODE_END(); } } else { // // Timeout occurs for an NVMe command. Reset the controller to abort the // outstanding commands. // DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: Timeout occurs for an NVMe command.\n")); // // Disable the timer to trigger the process of async transfers temporarily. // Status = gBS->SetTimer (Private->TimerEvent, TimerCancel, 0); if (EFI_ERROR (Status)) { goto EXIT; } // // Reset the NVMe controller. // Status = NvmeControllerInit (Private); if (!EFI_ERROR (Status)) { Status = AbortAsyncPassThruTasks (Private); if (!EFI_ERROR (Status)) { // // Re-enable the timer to trigger the process of async transfers. // Status = gBS->SetTimer (Private->TimerEvent, TimerPeriodic, NVME_HC_ASYNC_TIMER); if (!EFI_ERROR (Status)) { // // Return EFI_TIMEOUT to indicate a timeout occurs for NVMe PassThru command. // Status = EFI_TIMEOUT; } } } else { Status = EFI_DEVICE_ERROR; } goto EXIT; } if ((Private->CqHdbl[QueueId].Cqh ^= 1) == 0) { Private->Pt[QueueId] ^= 1; } Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]); Status = PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint32, NVME_BAR, NVME_CQHDBL_OFFSET(QueueId, Private->Cap.Dstrd), 1, &Data ); // // For now, the code does not support the non-blocking feature for admin queue. // If Event is not NULL for admin queue, signal the caller's event here. // if (Event != NULL) { ASSERT (QueueId == 0); gBS->SignalEvent (Event); } EXIT: if (MapData != NULL) { PciIo->Unmap ( PciIo, MapData ); } if (MapMeta != NULL) { PciIo->Unmap ( PciIo, MapMeta ); } if (MapPrpList != NULL) { PciIo->Unmap ( PciIo, MapPrpList ); } if (Prp != NULL) { PciIo->FreeBuffer (PciIo, PrpListNo, PrpListHost); } if (TimerEvent != NULL) { gBS->CloseEvent (TimerEvent); } 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 function is RDMSR handler for SMM. @param Index CPU index **/ VOID SmmReadMsrHandler ( IN UINT32 Index ) { UINT64 Data64; UINT32 MsrIndex; X86_REGISTER *Reg; STM_RSC_MSR_DESC *MsrDesc; STM_RSC_MSR_DESC LocalMsrDesc; Reg = &mGuestContextCommonSmm.GuestContextPerCpu[Index].Register; MsrIndex = ReadUnaligned32 ((UINT32 *)&Reg->Rcx); MsrDesc = GetStmResourceMsr (mHostContextCommon.MleProtectedResource.Base, MsrIndex); if ((MsrDesc != NULL) && (MsrDesc->ReadMask != 0)) { DEBUG ((EFI_D_ERROR, "RDMSR (%x) violation!\n", MsrIndex)); AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)MsrDesc); SmmExceptionHandler (Index); CpuDeadLoop (); } MsrDesc = GetStmResourceMsr ((STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr, MsrIndex); if ((MsrDesc == NULL) || (MsrDesc->ReadMask == 0) || (MsrDesc->KernelModeProcessing == 0)) { ZeroMem (&LocalMsrDesc, sizeof(LocalMsrDesc)); LocalMsrDesc.Hdr.RscType = MACHINE_SPECIFIC_REG; LocalMsrDesc.Hdr.Length = sizeof(LocalMsrDesc); LocalMsrDesc.MsrIndex = MsrIndex; LocalMsrDesc.ReadMask = (UINT64)-1; LocalMsrDesc.WriteMask = 0; AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)&LocalMsrDesc); } // DEBUG ((EFI_D_INFO, "!!!ReadMsrHandler!!!\n")); switch (MsrIndex) { case IA32_EFER_MSR_INDEX: Data64 = mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer; break; case IA32_SYSENTER_CS_MSR_INDEX: Data64 = (UINT64)VmRead32 (VMCS_32_GUEST_IA32_SYSENTER_CS_INDEX); break; case IA32_SYSENTER_ESP_MSR_INDEX: Data64 = (UINT64)VmReadN (VMCS_N_GUEST_IA32_SYSENTER_ESP_INDEX); break; case IA32_SYSENTER_EIP_MSR_INDEX: Data64 = (UINT64)VmReadN (VMCS_N_GUEST_IA32_SYSENTER_EIP_INDEX); break; case IA32_FS_BASE_MSR_INDEX: Data64 = (UINT64)VmReadN (VMCS_N_GUEST_FS_BASE_INDEX); break; case IA32_GS_BASE_MSR_INDEX: Data64 = (UINT64)VmReadN (VMCS_N_GUEST_GS_BASE_INDEX); break; default: // // For rest one, we need pass back to BIOS // Data64 = AsmReadMsr64 (MsrIndex); // // Need mask read item // MsrDesc = GetStmResourceMsr (mHostContextCommon.MleProtectedResource.Base, MsrIndex); if (MsrDesc != NULL) { Data64 &= MsrDesc->ReadMask; } break; } Reg->Rax = (UINTN)(UINT32)Data64; // HIGH bits are cleared Reg->Rdx = (UINTN)(UINT32)RShiftU64 (Data64, 32); // HIGH bits are cleared VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX)); return ; }
/** Build the Boot#### or Driver#### option from the VariableName. @param VariableName Variable name of the load option @param VendorGuid Variable GUID of the load option @param Option Return the load option. @retval EFI_SUCCESS Get the option just been created @retval EFI_NOT_FOUND Failed to get the new option **/ EFI_STATUS EFIAPI EfiBootManagerVariableToLoadOptionEx ( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *Option ) { EFI_STATUS Status; UINT32 Attribute; UINT16 FilePathSize; UINT8 *Variable; UINT8 *VariablePtr; UINTN VariableSize; EFI_DEVICE_PATH_PROTOCOL *FilePath; UINT8 *OptionalData; UINT32 OptionalDataSize; CHAR16 *Description; EFI_BOOT_MANAGER_LOAD_OPTION_TYPE OptionType; UINT16 OptionNumber; if ((VariableName == NULL) || (Option == NULL)) { return EFI_INVALID_PARAMETER; } if (!BmIsValidLoadOptionVariableName (VariableName, &OptionType, &OptionNumber)) { return EFI_INVALID_PARAMETER; } // // Read the variable // GetVariable2 (VariableName, VendorGuid, (VOID **) &Variable, &VariableSize); if (Variable == NULL) { return EFI_NOT_FOUND; } // // Validate *#### variable data. // if (!BmValidateOption(Variable, VariableSize)) { FreePool (Variable); return EFI_INVALID_PARAMETER; } // // Get the option attribute // VariablePtr = Variable; Attribute = ReadUnaligned32 ((UINT32 *) VariablePtr); VariablePtr += sizeof (UINT32); // // Get the option's device path size // FilePathSize = ReadUnaligned16 ((UINT16 *) VariablePtr); VariablePtr += sizeof (UINT16); // // Get the option's description string // Description = (CHAR16 *) VariablePtr; // // Get the option's description string size // VariablePtr += StrSize ((CHAR16 *) VariablePtr); // // Get the option's device path // FilePath = (EFI_DEVICE_PATH_PROTOCOL *) VariablePtr; VariablePtr += FilePathSize; OptionalDataSize = (UINT32) (VariableSize - (UINTN) (VariablePtr - Variable)); if (OptionalDataSize == 0) { OptionalData = NULL; } else { OptionalData = VariablePtr; } Status = EfiBootManagerInitializeLoadOption ( Option, OptionNumber, OptionType, Attribute, Description, FilePath, OptionalData, OptionalDataSize ); ASSERT_EFI_ERROR (Status); CopyGuid (&Option->VendorGuid, VendorGuid); FreePool (Variable); return Status; }
/** Look for the formset GUID which has the gEfiHiiDriverHealthFormsetGuid class GUID in the specified HII package list. @param Handle Handle to the HII package list. @param FormsetGuid Return the formset GUID. @retval EFI_SUCCESS The formset is found successfully. @retval EFI_NOT_FOUND The formset cannot be found. **/ EFI_STATUS DriverHealthManagerGetFormsetId ( IN EFI_HII_HANDLE Handle, OUT EFI_GUID *FormsetGuid ) { EFI_STATUS Status; EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; UINTN BufferSize; UINT8 *Package; UINT8 *OpCodeData; UINT32 Offset; UINT32 Offset2; EFI_HII_PACKAGE_HEADER PackageHeader; UINT8 Index; UINT8 NumberOfClassGuid; EFI_GUID *ClassGuid; // // Get HII PackageList // BufferSize = 0; HiiPackageList = NULL; Status = mDriverHealthManagerDatabase->ExportPackageLists (mDriverHealthManagerDatabase, Handle, &BufferSize, HiiPackageList); if (Status == EFI_BUFFER_TOO_SMALL) { HiiPackageList = AllocatePool (BufferSize); ASSERT (HiiPackageList != NULL); Status = mDriverHealthManagerDatabase->ExportPackageLists (mDriverHealthManagerDatabase, Handle, &BufferSize, HiiPackageList); } if (EFI_ERROR (Status)) { return Status; } ASSERT (HiiPackageList != NULL); // // Get Form package from this HII package List // for (Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); Offset < ReadUnaligned32 (&HiiPackageList->PackageLength); Offset += PackageHeader.Length) { Package = ((UINT8 *) HiiPackageList) + Offset; CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { // // Search FormSet in this Form Package // for (Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); Offset2 < PackageHeader.Length; Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length) { OpCodeData = Package + Offset2; if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) && (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags))) { // // Try to compare against formset class GUID // NumberOfClassGuid = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); ClassGuid = (EFI_GUID *) (OpCodeData + sizeof (EFI_IFR_FORM_SET)); for (Index = 0; Index < NumberOfClassGuid; Index++) { if (CompareGuid (&gEfiHiiDriverHealthFormsetGuid, &ClassGuid[Index])) { CopyMem (FormsetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)); FreePool (HiiPackageList); return EFI_SUCCESS; } } } } } } // // Form package not found in this Package List // FreePool (HiiPackageList); return EFI_NOT_FOUND; }
/** This function performs a read-modify-write operation on the contents 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. Type EFI_PEI_PCI_CFG_PPI_WIDTH is defined in Read(). @param Address The physical address of the access. @param SetBits Points to value to bitwise-OR with the read configuration value. The size of the value is determined by Width. @param ClearBits Points to the value to negate and bitwise-AND with the read configuration value. The size of the value is determined by Width. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER The invalid access width. **/ EFI_STATUS EFIAPI PciCfg2Modify ( 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 VOID *SetBits, IN VOID *ClearBits ) { UINTN PciLibAddress; UINT16 ClearValue16; UINT16 SetValue16; UINT32 ClearValue32; UINT32 SetValue32; PciLibAddress = PciCfgAddressConvert ((EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS *) &Address); if (Width == EfiPeiPciCfgWidthUint8) { PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits)); } else if (Width == EfiPeiPciCfgWidthUint16) { if ((PciLibAddress & 0x01) == 0) { // // Aligned Pci address access // ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits)); SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits); PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16); } else { // // Unaligned Pci address access, break up the request into byte by byte. // PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits)); PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1)); } } else if (Width == EfiPeiPciCfgWidthUint32) { if ((PciLibAddress & 0x03) == 0) { // // Aligned Pci address access // ClearValue32 = (UINT32) (~ReadUnaligned32 ((UINT32 *) ClearBits)); SetValue32 = ReadUnaligned32 ((UINT32 *) SetBits); PciAndThenOr32 (PciLibAddress, ClearValue32, SetValue32); } else if ((PciLibAddress & 0x01) == 0) { // // Unaligned Pci address access, break up the request into word by word. // ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits)); SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits); PciAndThenOr16 (PciLibAddress, ClearValue16, SetValue16); ClearValue16 = (UINT16) (~ReadUnaligned16 ((UINT16 *) ClearBits + 1)); SetValue16 = ReadUnaligned16 ((UINT16 *) SetBits + 1); PciAndThenOr16 (PciLibAddress + 2, ClearValue16, SetValue16); } else { // // Unaligned Pci address access, break up the request into byte by byte. // PciAndThenOr8 (PciLibAddress, (UINT8) (~(*(UINT8 *) ClearBits)), *((UINT8 *) SetBits)); PciAndThenOr8 (PciLibAddress + 1, (UINT8) (~(*((UINT8 *) ClearBits + 1))), *((UINT8 *) SetBits + 1)); PciAndThenOr8 (PciLibAddress + 2, (UINT8) (~(*((UINT8 *) ClearBits + 2))), *((UINT8 *) SetBits + 2)); PciAndThenOr8 (PciLibAddress + 3, (UINT8) (~(*((UINT8 *) ClearBits + 3))), *((UINT8 *) SetBits + 3)); } } else { return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
/** Call back function when the timer event is signaled. @param[in] Event The Event this notify function registered to. @param[in] Context Pointer to the context data registered to the Event. **/ VOID EFIAPI ProcessAsyncTaskList ( IN EFI_EVENT Event, IN VOID* Context ) { NVME_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; NVME_CQ *Cq; UINT16 QueueId; UINT32 Data; LIST_ENTRY *Link; LIST_ENTRY *NextLink; NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; NVME_BLKIO2_SUBTASK *Subtask; NVME_BLKIO2_REQUEST *BlkIo2Request; EFI_BLOCK_IO2_TOKEN *Token; BOOLEAN HasNewItem; EFI_STATUS Status; Private = (NVME_CONTROLLER_PRIVATE_DATA*)Context; QueueId = 2; Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; HasNewItem = FALSE; PciIo = Private->PciIo; // // Submit asynchronous subtasks to the NVMe Submission Queue // for (Link = GetFirstNode (&Private->UnsubmittedSubtasks); !IsNull (&Private->UnsubmittedSubtasks, Link); Link = NextLink) { NextLink = GetNextNode (&Private->UnsubmittedSubtasks, Link); Subtask = NVME_BLKIO2_SUBTASK_FROM_LINK (Link); BlkIo2Request = Subtask->BlockIo2Request; Token = BlkIo2Request->Token; RemoveEntryList (Link); BlkIo2Request->UnsubmittedSubtaskNum--; // // If any previous subtask fails, do not process subsequent ones. // if (Token->TransactionStatus != EFI_SUCCESS) { if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && BlkIo2Request->LastSubtaskSubmitted && (BlkIo2Request->UnsubmittedSubtaskNum == 0)) { // // Remove the BlockIo2 request from the device asynchronous queue. // RemoveEntryList (&BlkIo2Request->Link); FreePool (BlkIo2Request); gBS->SignalEvent (Token->Event); } FreePool (Subtask->CommandPacket->NvmeCmd); FreePool (Subtask->CommandPacket->NvmeCompletion); FreePool (Subtask->CommandPacket); FreePool (Subtask); continue; } Status = Private->Passthru.PassThru ( &Private->Passthru, Subtask->NamespaceId, Subtask->CommandPacket, Subtask->Event ); if (Status == EFI_NOT_READY) { InsertHeadList (&Private->UnsubmittedSubtasks, Link); BlkIo2Request->UnsubmittedSubtaskNum++; break; } else if (EFI_ERROR (Status)) { Token->TransactionStatus = EFI_DEVICE_ERROR; if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && Subtask->IsLast) { // // Remove the BlockIo2 request from the device asynchronous queue. // RemoveEntryList (&BlkIo2Request->Link); FreePool (BlkIo2Request); gBS->SignalEvent (Token->Event); } FreePool (Subtask->CommandPacket->NvmeCmd); FreePool (Subtask->CommandPacket->NvmeCompletion); FreePool (Subtask->CommandPacket); FreePool (Subtask); } else { InsertTailList (&BlkIo2Request->SubtasksQueue, Link); if (Subtask->IsLast) { BlkIo2Request->LastSubtaskSubmitted = TRUE; } } } while (Cq->Pt != Private->Pt[QueueId]) { ASSERT (Cq->Sqid == QueueId); HasNewItem = TRUE; // // Find the command with given Command Id. // for (Link = GetFirstNode (&Private->AsyncPassThruQueue); !IsNull (&Private->AsyncPassThruQueue, Link); Link = NextLink) { NextLink = GetNextNode (&Private->AsyncPassThruQueue, Link); AsyncRequest = NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link); if (AsyncRequest->CommandId == Cq->Cid) { // // Copy the Respose Queue entry for this command to the callers // response buffer. // CopyMem ( AsyncRequest->Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION) ); // // Free the resources allocated before cmd submission // if (AsyncRequest->MapData != NULL) { PciIo->Unmap (PciIo, AsyncRequest->MapData); } if (AsyncRequest->MapMeta != NULL) { PciIo->Unmap (PciIo, AsyncRequest->MapMeta); } if (AsyncRequest->MapPrpList != NULL) { PciIo->Unmap (PciIo, AsyncRequest->MapPrpList); } if (AsyncRequest->PrpListHost != NULL) { PciIo->FreeBuffer ( PciIo, AsyncRequest->PrpListNo, AsyncRequest->PrpListHost ); } RemoveEntryList (Link); gBS->SignalEvent (AsyncRequest->CallerEvent); FreePool (AsyncRequest); // // Update submission queue head. // Private->AsyncSqHead = Cq->Sqhd; break; } } Private->CqHdbl[QueueId].Cqh++; if (Private->CqHdbl[QueueId].Cqh > NVME_ASYNC_CCQ_SIZE) { Private->CqHdbl[QueueId].Cqh = 0; Private->Pt[QueueId] ^= 1; } Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; } if (HasNewItem) { Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]); PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint32, NVME_BAR, NVME_CQHDBL_OFFSET(QueueId, Private->Cap.Dstrd), 1, &Data ); } }
/** Check whether the PKCS7 signedData is revoked by verifying with the revoked certificates database, and if the signedData is timestamped, the embedded timestamp couterSignature will be checked with the supplied timestamp database. @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7 signature. @param[in] SignedDataSize The size of SignedData buffer in bytes. @param[in] InData Pointer to the buffer containing the raw message data previously signed and to be verified. @param[in] InDataSize The size of InData buffer in bytes. @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST structure which contains list of X.509 certificates of revoked signers and revoked content hashes. @param[in] TimeStampDb Pointer to a list of pointers to EFI_SIGNATURE_LIST structures which is used to pass a list of X.509 certificates of trusted timestamp signers. @retval EFI_SUCCESS The PKCS7 signedData is revoked. @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData. @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero. AllowedDb is NULL. Content is not NULL and ContentSize is NULL. @retval EFI_NOT_FOUND Content not found because InData is NULL and no content embedded in PKCS7 signedData. @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted. **/ EFI_STATUS P7CheckRevocation ( IN UINT8 *SignedData, IN UINTN SignedDataSize, IN UINT8 *InData, IN UINTN InDataSize, IN EFI_SIGNATURE_LIST **RevokedDb, IN EFI_SIGNATURE_LIST **TimeStampDb ) { EFI_STATUS Status; EFI_SIGNATURE_LIST *SigList; EFI_SIGNATURE_DATA *SigData; UINT8 *RevokedCert; UINTN RevokedCertSize; UINTN Index; UINT8 *CertBuffer; UINTN BufferLength; UINT8 *TrustedCert; UINTN TrustedCertLength; UINT8 CertNumber; UINT8 *CertPtr; UINT8 *Cert; UINTN CertSize; EFI_TIME RevocationTime; Status = EFI_UNSUPPORTED; SigData = NULL; RevokedCert = NULL; RevokedCertSize = 0; CertBuffer = NULL; TrustedCert = NULL; // // The signedData is revoked if the hash of content existed in RevokedDb // if (IsContentHashRevoked (InData, InDataSize, RevokedDb)) { Status = EFI_SUCCESS; goto _Exit; } // // Check if the signer's certificate can be found in Revoked database // for (Index = 0; ; Index++) { SigList = (EFI_SIGNATURE_LIST *)(RevokedDb[Index]); // // The list is terminated by a NULL pointer. // if (SigList == NULL) { break; } // // Ignore any non-X509-format entry in the list. // if (!CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) { continue; } SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) + SigList->SignatureHeaderSize); RevokedCert = SigData->SignatureData; RevokedCertSize = SigList->SignatureSize - sizeof (EFI_GUID); // // Verifying the PKCS#7 SignedData with the revoked certificate in RevokedDb // if (Pkcs7Verify (SignedData, SignedDataSize, RevokedCert, RevokedCertSize, InData, InDataSize)) { // // The signedData was verified by one entry in Revoked Database // Status = EFI_SUCCESS; break; } } if (!EFI_ERROR (Status)) { // // The signedData was revoked, since it was hit by RevokedDb // goto _Exit; } // // Now we will continue to check the X.509 Certificate Hash & Possible Timestamp // if ((TimeStampDb == NULL) || (*TimeStampDb == NULL)) { goto _Exit; } Pkcs7GetSigners (SignedData, SignedDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength); if ((BufferLength == 0) || (CertBuffer == NULL)) { Status = EFI_SUCCESS; goto _Exit; } // // Check if any hash of certificates embedded in P7 data is in the revoked database. // CertNumber = (UINT8) (*CertBuffer); CertPtr = CertBuffer + 1; for (Index = 0; Index < CertNumber; Index++) { // // Retrieve the Certificate data // CertSize = (UINTN) ReadUnaligned32 ((UINT32 *) CertPtr); Cert = (UINT8 *)CertPtr + sizeof (UINT32); if (IsCertHashRevoked (Cert, CertSize, RevokedDb, &RevocationTime)) { // // Check the timestamp signature and signing time to determine if p7 data can be trusted. // Status = EFI_SUCCESS; if (IsValidTimestamp (SignedData, SignedDataSize, TimeStampDb, &RevocationTime)) { // // Use EFI_NOT_READY to identify the P7Data is not reovked, because the timestamping // occured prior to the time of certificate revocation. // Status = EFI_NOT_READY; } goto _Exit; } CertPtr = CertPtr + sizeof (UINT32) + CertSize; } _Exit: Pkcs7FreeSigners (CertBuffer); Pkcs7FreeSigners (TrustedCert); return Status; }
EFI_STATUS BootOptionStart ( IN BDS_LOAD_OPTION *BootOption ) { EFI_STATUS Status; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; UINT32 LoaderType; ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath; EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath; UINTN FdtDevicePathSize; UINTN CmdLineSize; UINTN InitrdSize; EFI_DEVICE_PATH* Initrd; UINT16 LoadOptionIndexSize; if (IS_ARM_BDS_BOOTENTRY (BootOption)) { Status = EFI_UNSUPPORTED; OptionalData = BootOption->OptionalData; LoaderType = ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); if (LoaderType == BDS_LOADER_EFI_APPLICATION) { if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_APP) { // Need to connect every drivers to ensure no dependencies are missing for the application BdsConnectAllDrivers (); } Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, 0, NULL); } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) { LinuxArguments = &(OptionalData->Arguments.LinuxArguments); CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); if (InitrdSize > 0) { Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize)); } else { Initrd = NULL; } Status = BdsBootLinuxAtag (BootOption->FilePathList, Initrd, // Initrd (CHAR8*)(LinuxArguments + 1)); // CmdLine } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) { LinuxArguments = &(OptionalData->Arguments.LinuxArguments); CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); if (InitrdSize > 0) { Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize)); } else { Initrd = NULL; } // Get the default FDT device path Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); ASSERT_EFI_ERROR(Status); DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); // Get the FDT device path FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); ASSERT_EFI_ERROR(Status); Status = BdsBootLinuxFdt (BootOption->FilePathList, Initrd, // Initrd (CHAR8*)(LinuxArguments + 1), FdtDevicePath); FreePool (DefaultFdtDevicePath); FreePool (FdtDevicePath); } } else { // Connect all the drivers if the EFI Application is not a EFI OS Loader if ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_APP) { BdsConnectAllDrivers (); } // Set BootCurrent variable LoadOptionIndexSize = sizeof(UINT16); gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, LoadOptionIndexSize, &(BootOption->LoadOptionIndex)); Status = BdsStartEfiApplication (gImageHandle, BootOption->FilePathList, BootOption->OptionalDataSize, BootOption->OptionalData); // Clear BootCurrent variable LoadOptionIndexSize = sizeof(UINT16); gRT->SetVariable (L"BootCurrent", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL); } return Status; }
/** This command is used to cause an update to the indicated PCR. The data in eventData is hashed using the hash algorithm associated with each bank in which the indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in TPM2_PCR_Extend(). A TPM shall support an Event.size of zero through 1,024 inclusive. @param[in] PcrHandle Handle of the PCR @param[in] EventData Event data in sized buffer @param[out] Digests List of digest @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR Unexpected device behavior. **/ EFI_STATUS EFIAPI Tpm2PcrEvent ( IN TPMI_DH_PCR PcrHandle, IN TPM2B_EVENT *EventData, OUT TPML_DIGEST_VALUES *Digests ) { EFI_STATUS Status; TPM2_PCR_EVENT_COMMAND Cmd; TPM2_PCR_EVENT_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_Event); Cmd.PcrHandle = SwapBytes32(PcrHandle); // // Add in Auth session // Buffer = (UINT8 *)&Cmd.AuthSessionPcr; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer); Buffer += SessionInfoSize; Cmd.AuthorizationSize = SwapBytes32(SessionInfoSize); // Event WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(EventData->size)); Buffer += sizeof(UINT16); CopyMem (Buffer, EventData->buffer, EventData->size); Buffer += EventData->size; 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, "Tpm2PcrEvent: 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, "Tpm2PcrEvent: 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, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32(Res.Header.responseCode))); return EFI_DEVICE_ERROR; } // // Unmarshal the response // Buffer = (UINT8 *)&Res.Digests; Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer)); Buffer += sizeof(UINT32); for (Index = 0; Index < Digests->count; Index++) { Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); 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( &Digests->digests[Index].digest, Buffer, DigestSize ); Buffer += DigestSize; } return EFI_SUCCESS; }
/** This service enables the sending of commands to the TPM12. @param[in] InputParameterBlockSize Size of the TPM12 input parameter block. @param[in] InputParameterBlock Pointer to the TPM12 input parameter block. @param[in,out] OutputParameterBlockSize Size of the TPM12 output parameter block. @param[in] OutputParameterBlock Pointer to the TPM12 output parameter block. @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. **/ EFI_STATUS EFIAPI Tpm12SubmitCommand ( IN UINT32 InputParameterBlockSize, IN UINT8 *InputParameterBlock, IN OUT UINT32 *OutputParameterBlockSize, IN UINT8 *OutputParameterBlock ) { EFI_STATUS Status; UINT32 TpmOutSize; TPM_RSP_COMMAND_HDR *ResponseHeader; UINT64 Current; UINT64 Previous; UINT64 Total; UINT64 Start; UINT64 End; UINT64 Timeout; INT64 Cycle; INT64 Delta; // // Make sure response buffer is big enough to hold a response header // if (*OutputParameterBlockSize < sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_BUFFER_TOO_SMALL; goto Done; } // // Get the current timer value // Current = GetPerformanceCounter(); // // Initialize local variables // Start = 0; End = 0; Total = 0; // // Retrieve the performance counter properties and compute the number of // performance counter ticks required to reach the maximum TIS timeout of // TIS_TIMEOUT_A. TIS_TIMEOUT_A is in microseconds. // Timeout = DivU64x32 ( MultU64x32 ( GetPerformanceCounterProperties (&Start, &End), TIS_TIMEOUT_A ), 1000000 ); Cycle = End - Start; if (Cycle < 0) { Cycle = -Cycle; } Cycle++; // // Send command // do { Status = WriteTpmBufferMultiple (InputParameterBlock, InputParameterBlockSize); Previous = Current; Current = GetPerformanceCounter(); Delta = (INT64) (Current - Previous); if (Start > End) { Delta = -Delta; } if (Delta < 0) { Delta += Cycle; } Total += Delta; if (Total >= Timeout) { Status = EFI_TIMEOUT; goto Done; } } while (EFI_ERROR (Status)); // // Receive response header // do { Status = ReadTpmBufferMultiple (OutputParameterBlock, sizeof (TPM_RSP_COMMAND_HDR)); Previous = Current; Current = GetPerformanceCounter(); Delta = (INT64) (Current - Previous); if (Start > End) { Delta = -Delta; } if (Delta < 0) { Delta += Cycle; } Total += Delta; if (Total >= Timeout) { Status = EFI_TIMEOUT; goto Done; } } while (EFI_ERROR (Status)); // // Check the response data header (tag, parasize and returncode) // ResponseHeader = (TPM_RSP_COMMAND_HDR *)OutputParameterBlock; if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader->tag)) != TPM_TAG_RSP_COMMAND) { Status = EFI_DEVICE_ERROR; goto Done; } TpmOutSize = SwapBytes32 (ReadUnaligned32 (&ResponseHeader->paramSize)); if (TpmOutSize == sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_SUCCESS; goto Done; } if (TpmOutSize < sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_DEVICE_ERROR; goto Done; } if (*OutputParameterBlockSize < TpmOutSize) { Status = EFI_BUFFER_TOO_SMALL; goto Done; } *OutputParameterBlockSize = TpmOutSize; // // Receive the remaining data in the response header // do { Status = ReadTpmBufferMultiple ( OutputParameterBlock + sizeof (TPM_RSP_COMMAND_HDR), TpmOutSize - sizeof (TPM_RSP_COMMAND_HDR) ); Previous = Current; Current = GetPerformanceCounter(); Delta = (INT64) (Current - Previous); if (Start > End) { Delta = -Delta; } if (Delta < 0) { Delta += Cycle; } Total += Delta; if (Total >= Timeout) { Status = EFI_TIMEOUT; goto Done; } } while (EFI_ERROR (Status)); Done: DEBUG (( EFI_D_VERBOSE, "Tpm12SubmitCommand() Status = %r Time = %ld ms\n", Status, DivU64x64Remainder ( MultU64x32 (Total, 1000), GetPerformanceCounterProperties (NULL, NULL), NULL ) )); return Status; }
/** Copies the data in a caller supplied buffer to a specified range of PCI configuration space. Writes the range of PCI configuration registers specified by StartAddress and Size from the buffer specified by Buffer. This function only allows the PCI configuration registers from a single PCI function to be written. Size is returned. When possible 32-bit PCI configuration write cycles are used to write from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit and 16-bit PCI configuration write 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 containing the data to write. @return Size written to StartAddress. **/ UINTN EFIAPI PciWriteBuffer ( IN UINTN StartAddress, IN UINTN Size, IN VOID *Buffer ) { UINTN ReturnValue; ASSERT_INVALID_PCI_ADDRESS (StartAddress, 0); ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000); if (Size == 0) { return 0; } ASSERT (Buffer != NULL); // // Save Size for return // ReturnValue = Size; if ((StartAddress & BIT0) != 0) { // // Write a byte if StartAddress is byte aligned // PciWrite8 (StartAddress, *(UINT8*)Buffer); StartAddress += sizeof (UINT8); Size -= sizeof (UINT8); Buffer = (UINT8*)Buffer + 1; } if (Size >= sizeof (UINT16) && (StartAddress & BIT1) != 0) { // // Write a word if StartAddress is word aligned // PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); StartAddress += sizeof (UINT16); Size -= sizeof (UINT16); Buffer = (UINT16*)Buffer + 1; } while (Size >= sizeof (UINT32)) { // // Write as many double words as possible // PciWrite32 (StartAddress, ReadUnaligned32 (Buffer)); StartAddress += sizeof (UINT32); Size -= sizeof (UINT32); Buffer = (UINT32*)Buffer + 1; } if (Size >= sizeof (UINT16)) { // // Write the last remaining word if exist // PciWrite16 (StartAddress, ReadUnaligned16 (Buffer)); StartAddress += sizeof (UINT16); Size -= sizeof (UINT16); Buffer = (UINT16*)Buffer + 1; } if (Size >= sizeof (UINT8)) { // // Write the last remaining byte if exist // PciWrite8 (StartAddress, *(UINT8*)Buffer); } return ReturnValue; }
EFI_STATUS BootMenuUpdateBootOption ( IN LIST_ENTRY *BootOptionsList ) { EFI_STATUS Status; BDS_LOAD_OPTION_ENTRY *BootOptionEntry; BDS_LOAD_OPTION *BootOption; BDS_LOAD_OPTION_SUPPORT* DeviceSupport; ARM_BDS_LOADER_ARGUMENTS* BootArguments; CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX]; CHAR16 UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX]; EFI_DEVICE_PATH *DevicePath; EFI_DEVICE_PATH *TempInitrdPath; ARM_BDS_LOADER_TYPE BootType; ARM_BDS_LOADER_OPTIONAL_DATA* LoaderOptionalData; ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; EFI_DEVICE_PATH *InitrdPathNodes; EFI_DEVICE_PATH *InitrdPath; UINTN InitrdSize; UINTN CmdLineSize; BOOLEAN InitrdSupport; UINT8* OptionalData; UINTN OptionalDataSize; BOOLEAN IsPrintable; BOOLEAN IsUnicode; DisplayBootOptions (BootOptionsList); Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry); if (EFI_ERROR (Status)) { return Status; } BootOption = BootOptionEntry->BdsLoadOption; // Get the device support for this Boot Option Status = BootDeviceGetDeviceSupport (BootOption->FilePathList, &DeviceSupport); if (EFI_ERROR(Status)) { Print(L"Not possible to retrieve the supported device for the update\n"); return EFI_UNSUPPORTED; } Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (DeviceSupport->RequestBootType) { Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } } LoaderOptionalData = BootOption->OptionalData; if (LoaderOptionalData != NULL) { BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType)); } else { BootType = BDS_LOADER_EFI_APPLICATION; } if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { LinuxArguments = &LoaderOptionalData->Arguments.LinuxArguments; CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); if (InitrdSize > 0) { Print(L"Keep the initrd: "); } else { Print(L"Add an initrd: "); } Status = GetHIInputBoolean (&InitrdSupport); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (InitrdSupport) { if (InitrdSize > 0) { // Case we update the initrd device path Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; } InitrdSize = GetDevicePathSize (InitrdPath); } else { // Case we create the initrd device path Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; } if (InitrdPathNodes != NULL) { // Duplicate Linux kernel Device Path TempInitrdPath = DuplicateDevicePath (BootOption->FilePathList); // Replace Linux kernel Node by EndNode SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath)); // Append the Device Path to the selected device path InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); FreePool (TempInitrdPath); // Free the InitrdPathNodes created by Support->CreateDevicePathNode() FreePool (InitrdPathNodes); if (InitrdPath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; } InitrdSize = GetDevicePathSize (InitrdPath); } else { InitrdPath = NULL; } } } else { InitrdSize = 0; } Print(L"Arguments to pass to the binary: "); if (CmdLineSize > 0) { AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine)); CmdLine[sizeof (CmdLine) - 1] = '\0'; } else { CmdLine[0] = '\0'; } Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } CmdLineSize = AsciiStrSize (CmdLine); OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize; BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; BootArguments->LinuxArguments.InitrdSize = InitrdSize; CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize); CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); OptionalData = (UINT8*)BootArguments; } else { Print (L"Arguments to pass to the EFI Application: "); if (BootOption->OptionalDataSize > 0) { IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode); if (IsPrintable) { // // The size in bytes of the string, final zero included, should // be equal to or at least lower than "BootOption->OptionalDataSize" // and the "IsPrintableString()" has already tested that the length // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX, // final '\0' included. We can thus copy the string for editing // using "CopyMem()". Furthermore, note that in the case of an Unicode // string "StrnCpy()" and "StrCpy()" can not be used to copy the // string because the data pointed to by "BootOption->OptionalData" // is not necessarily 2-byte aligned. // if (IsUnicode) { CopyMem ( UnicodeCmdLine, BootOption->OptionalData, MIN (sizeof (UnicodeCmdLine), BootOption->OptionalDataSize) ); } else { CopyMem ( CmdLine, BootOption->OptionalData, MIN (sizeof (CmdLine), BootOption->OptionalDataSize) ); } } } else { UnicodeCmdLine[0] = L'\0'; IsPrintable = TRUE; IsUnicode = TRUE; } // We do not request arguments for OptionalData that cannot be printed if (IsPrintable) { if (IsUnicode) { Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } OptionalData = (UINT8*)UnicodeCmdLine; OptionalDataSize = StrSize (UnicodeCmdLine); } else { Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } OptionalData = (UINT8*)CmdLine; OptionalDataSize = AsciiStrSize (CmdLine); } } else { // We keep the former OptionalData OptionalData = BootOption->OptionalData; OptionalDataSize = BootOption->OptionalDataSize; } } Print(L"Description for this new Entry: "); StrnCpy (BootDescription, BootOption->Description, BOOT_DEVICE_DESCRIPTION_MAX); Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } // Update the entry Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize); FREE_DEVICE_PATH: FreePool (DevicePath); EXIT: if (Status == EFI_ABORTED) { Print(L"\n"); } return Status; }
/** This function is WRMSR handler for SMM. @param Index CPU index **/ VOID SmmWriteMsrHandler ( IN UINT32 Index ) { UINT64 Data64; UINT32 MsrIndex; VM_ENTRY_CONTROLS VmEntryControls; X86_REGISTER *Reg; STM_RSC_MSR_DESC *MsrDesc; STM_RSC_MSR_DESC LocalMsrDesc; Reg = &mGuestContextCommonSmm.GuestContextPerCpu[Index].Register; MsrIndex = ReadUnaligned32 ((UINT32 *)&Reg->Rcx); MsrDesc = GetStmResourceMsr (mHostContextCommon.MleProtectedResource.Base, MsrIndex); if ((MsrDesc != NULL) && (MsrDesc->WriteMask != 0)) { DEBUG ((EFI_D_ERROR, "WRMSR (%x) violation!\n", MsrIndex)); AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)MsrDesc); SmmExceptionHandler (Index); CpuDeadLoop (); } MsrDesc = GetStmResourceMsr ((STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr, MsrIndex); if ((MsrDesc == NULL) || (MsrDesc->WriteMask == 0) || (MsrDesc->KernelModeProcessing == 0)) { ZeroMem (&LocalMsrDesc, sizeof(LocalMsrDesc)); LocalMsrDesc.Hdr.RscType = MACHINE_SPECIFIC_REG; LocalMsrDesc.Hdr.Length = sizeof(LocalMsrDesc); LocalMsrDesc.MsrIndex = MsrIndex; LocalMsrDesc.ReadMask = 0; LocalMsrDesc.WriteMask = (UINT64)-1; AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)&LocalMsrDesc); } // DEBUG ((EFI_D_INFO, "!!!WriteMsrHandler!!!\n")); Data64 = LShiftU64 ((UINT64)ReadUnaligned32 ((UINT32 *)&Reg->Rdx), 32) | (UINT64)ReadUnaligned32 ((UINT32 *)&Reg->Rax); switch (MsrIndex) { case IA32_EFER_MSR_INDEX: #if 0 AcquireSpinLock (&mHostContextCommon.DebugLock); if ((Data64 & IA32_EFER_MSR_SCE) != 0) { DEBUG ((EFI_D_INFO, "!!!WriteMsrHandler - SCE!!!\n")); } if ((Data64 & IA32_EFER_MSR_XDE) != 0) { DEBUG ((EFI_D_INFO, "!!!WriteMsrHandler - XDE!!!\n")); } ReleaseSpinLock (&mHostContextCommon.DebugLock); #endif mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer = Data64; // // Check IA32e mode switch // VmEntryControls.Uint32 = VmRead32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX); if ((Data64 & IA32_EFER_MSR_MLE) != 0) { mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer |= IA32_EFER_MSR_MLE; } else { mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer &= ~IA32_EFER_MSR_MLE; } if (((mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer & IA32_EFER_MSR_MLE) != 0) && ((VmReadN (VMCS_N_GUEST_CR0_INDEX) & CR0_PG) != 0)) { mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer |= IA32_EFER_MSR_MLA; VmEntryControls.Bits.Ia32eGuest = 1; } else { mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer &= ~IA32_EFER_MSR_MLA; VmEntryControls.Bits.Ia32eGuest = 0; } VmWrite32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX, VmEntryControls.Uint32); VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX, mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer); break; case IA32_SYSENTER_CS_MSR_INDEX: VmWrite32 (VMCS_32_GUEST_IA32_SYSENTER_CS_INDEX, (UINT32)Data64); break; case IA32_SYSENTER_ESP_MSR_INDEX: VmWriteN (VMCS_N_GUEST_IA32_SYSENTER_ESP_INDEX, (UINTN)Data64); break; case IA32_SYSENTER_EIP_MSR_INDEX: VmWriteN (VMCS_N_GUEST_IA32_SYSENTER_EIP_INDEX, (UINTN)Data64); break; case IA32_FS_BASE_MSR_INDEX: VmWriteN (VMCS_N_GUEST_FS_BASE_INDEX, (UINTN)Data64); AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use FS break; case IA32_GS_BASE_MSR_INDEX: VmWriteN (VMCS_N_GUEST_GS_BASE_INDEX, (UINTN)Data64); AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use GS break; #if 0 case IA32_KERNAL_GS_BASE_MSR_INDEX: AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this break; case IA32_STAR_MSR_INDEX: AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this break; case IA32_LSTAR_MSR_INDEX: AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this break; case IA32_FMASK_MSR_INDEX: AsmWriteMsr64 (MsrIndex, Data64); // VMM does not use this break; #endif case IA32_SMM_MONITOR_CTL_MSR_INDEX: break; case EFI_MSR_NEHALEM_SMRR_PHYS_BASE: case EFI_MSR_NEHALEM_SMRR_PHYS_MASK: // Ignore the write break; case IA32_BIOS_UPDT_TRIG_MSR_INDEX: // Only write it when BIOS request MicrocodeUpdate MsrDesc = GetStmResourceMsr ((STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr, IA32_BIOS_UPDT_TRIG_MSR_INDEX); if (MsrDesc != NULL) { AsmWriteMsr64 (MsrIndex, Data64); } break; default: // // For rest one, we need pass back to BIOS // // // Need mask write item // if (MsrDesc != NULL) { Data64 |= MsrDesc->WriteMask; } AsmWriteMsr64 (MsrIndex, Data64); break; } VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX)); return ; }
EFI_STATUS BootMenuMain ( VOID ) { LIST_ENTRY BootOptionsList; UINTN OptionCount; UINTN BootOptionCount; EFI_STATUS Status; LIST_ENTRY* Entry; BDS_LOAD_OPTION* BootOption; UINTN BootOptionSelected; UINTN Index; UINTN BootMainEntryCount; BOOLEAN IsUnicode; BootOption = NULL; BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY); while (TRUE) { // Get Boot#### list BootOptionList (&BootOptionsList); OptionCount = 1; // Display the Boot options for (Entry = GetFirstNode (&BootOptionsList); !IsNull (&BootOptionsList,Entry); Entry = GetNextNode (&BootOptionsList,Entry) ) { BootOption = LOAD_OPTION_FROM_LINK(Entry); Print(L"[%d] %s\n", OptionCount, BootOption->Description); DEBUG_CODE_BEGIN(); CHAR16* DevicePathTxt; EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; UINTN CmdLineSize; ARM_BDS_LOADER_TYPE LoaderType; Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); if (EFI_ERROR(Status)) { // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe) DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathToTextProtocol\n")); return Status; } DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootOption->FilePathList, TRUE, TRUE); Print(L"\t- %s\n",DevicePathTxt); // If it is a supported BootEntry then print its details if (IS_ARM_BDS_BOOTENTRY (BootOption)) { OptionalData = BootOption->OptionalData; LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) { if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) { CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize)), TRUE, TRUE); Print(L"\t- Initrd: %s\n", DevicePathTxt); } if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize) > 0) { Print(L"\t- Arguments: %a\n", (&OptionalData->Arguments.LinuxArguments + 1)); } } switch (LoaderType) { case BDS_LOADER_EFI_APPLICATION: Print(L"\t- LoaderType: EFI Application\n"); break; case BDS_LOADER_KERNEL_LINUX_ATAG: Print(L"\t- LoaderType: Linux kernel with ATAG support\n"); break; case BDS_LOADER_KERNEL_LINUX_FDT: Print(L"\t- LoaderType: Linux kernel with FDT support\n"); break; default: Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType); } } else if (BootOption->OptionalData != NULL) { if (IsPrintableString (BootOption->OptionalData, &IsUnicode)) { if (IsUnicode) { Print (L"\t- Arguments: %s\n", BootOption->OptionalData); } else { AsciiPrint ("\t- Arguments: %a\n", BootOption->OptionalData); } } } FreePool(DevicePathTxt); DEBUG_CODE_END(); OptionCount++; } BootOptionCount = OptionCount-1; // Display the hardcoded Boot entries for (Index = 0; Index < BootMainEntryCount; Index++) { Print(L"[%d] %s\n",OptionCount,BootMainEntries[Index]); OptionCount++; } // Request the boot entry from the user BootOptionSelected = 0; while (BootOptionSelected == 0) { Print(L"Start: "); Status = GetHIInputInteger (&BootOptionSelected); if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) { Print(L"Invalid input (max %d)\n",(OptionCount-1)); BootOptionSelected = 0; } } // Start the selected entry if (BootOptionSelected > BootOptionCount) { // Start the hardcoded entry Status = BootMainEntries[BootOptionSelected - BootOptionCount - 1].Callback (&BootOptionsList); } else { // Find the selected entry from the Boot#### list Index = 1; for (Entry = GetFirstNode (&BootOptionsList); !IsNull (&BootOptionsList,Entry); Entry = GetNextNode (&BootOptionsList,Entry) ) { if (Index == BootOptionSelected) { BootOption = LOAD_OPTION_FROM_LINK(Entry); break; } Index++; } Status = BootOptionStart (BootOption); } } // Should never go here }
/** 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 returns Returns a list of TPMS_ALG_PROPERTIES. Each entry is an algorithm ID and a set of properties of the algorithm. This function parse the value got from TPM2_GetCapability and return the list. @param[out] AlgList List of algorithm. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. **/ EFI_STATUS EFIAPI Tpm2GetCapabilitySupportedAlg ( OUT TPML_ALG_PROPERTY *AlgList ) { TPMS_CAPABILITY_DATA TpmCap; TPMI_YES_NO MoreData; UINTN Index; EFI_STATUS Status; Status = Tpm2GetCapability ( TPM_CAP_ALGS, 1, MAX_CAP_ALGS, &MoreData, &TpmCap ); if (EFI_ERROR (Status)) { return Status; } CopyMem (AlgList, &TpmCap.data.algorithms, sizeof (TPML_ALG_PROPERTY)); AlgList->count = SwapBytes32 (AlgList->count); for (Index = 0; Index < AlgList->count; Index++) { AlgList->algProperties[Index].alg = SwapBytes16 (AlgList->algProperties[Index].alg); WriteUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&AlgList->algProperties[Index].algProperties))); } return EFI_SUCCESS; }
/** Execute READ CAPACITY 16 bytes command to request information regarding the capacity of the installed medium of the device. This function executes READ CAPACITY 16 bytes command to get the capacity of the USB mass storage media, including the presence, block size, and last block number. @param UsbMass The device to retireve disk gemotric. @retval EFI_SUCCESS The disk geometry is successfully retrieved. @retval EFI_NOT_READY The returned block size is zero. @retval Other READ CAPACITY 16 bytes command execution failed. **/ EFI_STATUS UsbBootReadCapacity16 ( IN USB_MASS_DEVICE *UsbMass ) { UINT8 CapacityCmd[16]; EFI_SCSI_DISK_CAPACITY_DATA16 CapacityData; EFI_BLOCK_IO_MEDIA *Media; EFI_STATUS Status; UINT32 BlockSize; Media = &UsbMass->BlockIoMedia; Media->MediaPresent = FALSE; Media->LastBlock = 0; Media->BlockSize = 0; ZeroMem (CapacityCmd, sizeof (CapacityCmd)); ZeroMem (&CapacityData, sizeof (CapacityData)); CapacityCmd[0] = EFI_SCSI_OP_READ_CAPACITY16; CapacityCmd[1] = 0x10; // // Partial medium indicator, set the bytes 2 ~ 9 of the Cdb as ZERO. // ZeroMem ((CapacityCmd + 2), 8); CapacityCmd[13] = sizeof (CapacityData); Status = UsbBootExecCmdWithRetry ( UsbMass, CapacityCmd, (UINT8) sizeof (CapacityCmd), EfiUsbDataIn, &CapacityData, sizeof (CapacityData), USB_BOOT_GENERAL_CMD_TIMEOUT ); if (EFI_ERROR (Status)) { return Status; } // // Get the information on media presence, block size, and last block number // from READ CAPACITY data. // Media->MediaPresent = TRUE; Media->LastBlock = SwapBytes64 (ReadUnaligned64 ((CONST UINT64 *) &(CapacityData.LastLba7))); BlockSize = SwapBytes32 (ReadUnaligned32 ((CONST UINT32 *) &(CapacityData.BlockSize3))); Media->LowestAlignedLba = (CapacityData.LowestAlignLogic2 << 8) | CapacityData.LowestAlignLogic1; Media->LogicalBlocksPerPhysicalBlock = (1 << CapacityData.LogicPerPhysical); if (BlockSize == 0) { // // Get sense data // return UsbBootRequestSense (UsbMass); } else { Media->BlockSize = BlockSize; } return Status; }
/** Extract the displayed formset for given HII handle and class guid. @param Handle The HII handle. @param SetupClassGuid The class guid specifies which form set will be displayed. @param SkipCount Skip some formsets which has processed before. @param FormSetTitle Formset title string. @param FormSetHelp Formset help string. @param FormSetGuid Formset Guid. @retval TRUE The formset for given HII handle will be displayed. @return FALSE The formset for given HII handle will not be displayed. **/ BOOLEAN ExtractDisplayedHiiFormFromHiiHandle ( IN EFI_HII_HANDLE Handle, IN EFI_GUID *SetupClassGuid, IN UINTN SkipCount, OUT EFI_STRING_ID *FormSetTitle, OUT EFI_STRING_ID *FormSetHelp, OUT EFI_GUID *FormSetGuid ) { EFI_STATUS Status; UINTN BufferSize; EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; UINT8 *Package; UINT8 *OpCodeData; UINT32 Offset; UINT32 Offset2; UINT32 PackageListLength; EFI_HII_PACKAGE_HEADER PackageHeader; EFI_GUID *ClassGuid; UINT8 ClassGuidNum; BOOLEAN FoundAndSkip; ASSERT (Handle != NULL); ASSERT (SetupClassGuid != NULL && FormSetTitle != NULL && FormSetHelp != NULL && FormSetGuid != NULL); *FormSetTitle = 0; *FormSetHelp = 0; ClassGuidNum = 0; ClassGuid = NULL; FoundAndSkip = FALSE; // // Get HII PackageList // BufferSize = 0; HiiPackageList = NULL; Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); // // Handle is a invalid handle. Check if Handle is corrupted. // ASSERT (Status != EFI_NOT_FOUND); // // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. // ASSERT (Status == EFI_BUFFER_TOO_SMALL); HiiPackageList = AllocatePool (BufferSize); ASSERT (HiiPackageList != NULL); Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList); if (EFI_ERROR (Status)) { return FALSE; } // // Get Form package from this HII package List // Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength); while (Offset < PackageListLength) { Package = ((UINT8 *) HiiPackageList) + Offset; CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); Offset += PackageHeader.Length; if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { // // Search FormSet Opcode in this Form Package // Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); while (Offset2 < PackageHeader.Length) { OpCodeData = Package + Offset2; Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) { // // Find FormSet OpCode // ClassGuidNum = (UINT8) (((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3); ClassGuid = (EFI_GUID *) (VOID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET)); while (ClassGuidNum-- > 0) { if (CompareGuid (SetupClassGuid, ClassGuid)) { // // Check whether need to skip the formset. // if (SkipCount != 0) { SkipCount--; FoundAndSkip = TRUE; break; } CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); CopyGuid (FormSetGuid, (CONST EFI_GUID *)(&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)); FreePool (HiiPackageList); return TRUE; } ClassGuid ++; } if (FoundAndSkip) { break; } } else if (CompareGuid (SetupClassGuid, &gEfiHiiPlatformSetupFormsetGuid)) { // // Check whether need to skip the formset. // if (SkipCount != 0) { SkipCount--; break; } CopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); CopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); CopyGuid (FormSetGuid, (CONST EFI_GUID *)(&((EFI_IFR_FORM_SET *) OpCodeData)->Guid)); FreePool (HiiPackageList); return TRUE; } } } } } FreePool (HiiPackageList); return FALSE; }
/** This command is used to read the public area and Name of an NV Index. @param[in] NvIndex The NV Index. @param[out] NvPublic The public area of the index. @param[out] NvName The Name of the nvIndex. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. **/ EFI_STATUS EFIAPI Tpm2NvReadPublic ( IN TPMI_RH_NV_INDEX NvIndex, OUT TPM2B_NV_PUBLIC *NvPublic, OUT TPM2B_NAME *NvName ) { EFI_STATUS Status; TPM2_NV_READPUBLIC_COMMAND SendBuffer; TPM2_NV_READPUBLIC_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT16 NvPublicSize; UINT16 NvNameSize; UINT8 *Buffer; TPM_RC ResponseCode; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadPublic); SendBuffer.NvIndex = SwapBytes32 (NvIndex); SendBufferSize = (UINT32) sizeof (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, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); if (ResponseCode != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); } switch (ResponseCode) { case TPM_RC_SUCCESS: // return data break; case TPM_RC_HANDLE + RC_NV_ReadPublic_nvIndex: // TPM_RC_NV_DEFINED: return EFI_NOT_FOUND; case TPM_RC_VALUE + RC_NV_ReadPublic_nvIndex: return EFI_INVALID_PARAMETER; default: return EFI_DEVICE_ERROR; } if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_NOT_FOUND; } // // Basic check // NvPublicSize = SwapBytes16 (RecvBuffer.NvPublic.size); if (NvPublicSize > sizeof(TPMS_NV_PUBLIC)) { DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvPublic.size error %x\n", NvPublicSize)); return EFI_DEVICE_ERROR; } NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize))); if (NvNameSize > sizeof(TPMU_NAME)){ DEBUG ((DEBUG_ERROR, "Tpm2NvReadPublic - NvNameSize error %x\n", NvNameSize)); return EFI_DEVICE_ERROR; } if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x\n", RecvBufferSize)); return EFI_NOT_FOUND; } // // Return the response // CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize); NvPublic->size = NvPublicSize; NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex); NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg); WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size); Buffer = (UINT8 *)&RecvBuffer.NvPublic.nvPublic.authPolicy; Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size; NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); CopyMem (NvName->name, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16), NvNameSize); NvName->size = NvNameSize; return EFI_SUCCESS; }
/** Update Com Ports attributes from DevicePath @param DevicePath DevicePath that contains Com ports @retval EFI_SUCCESS The update is successful. @retval EFI_NOT_FOUND Can not find specific menu entry **/ EFI_STATUS UpdateComAttributeFromVariable ( EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_DEVICE_PATH_PROTOCOL *Node; EFI_DEVICE_PATH_PROTOCOL *SerialNode; ACPI_HID_DEVICE_PATH *Acpi; UART_DEVICE_PATH *Uart; UART_DEVICE_PATH *Uart1; UINTN TerminalNumber; BM_MENU_ENTRY *NewMenuEntry; BM_TERMINAL_CONTEXT *NewTerminalContext; UINTN Index; UART_FLOW_CONTROL_DEVICE_PATH *FlowControlNode; BOOLEAN HasFlowControlNode; HasFlowControlNode = FALSE; Node = DevicePath; Node = NextDevicePathNode (Node); TerminalNumber = 0; for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { while (!IsDevicePathEnd (Node)) { Acpi = (ACPI_HID_DEVICE_PATH *) Node; if (IsIsaSerialNode (Acpi)) { CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32)); } if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { Uart = (UART_DEVICE_PATH *) Node; NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber); if (NULL == NewMenuEntry) { return EFI_NOT_FOUND; } NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; CopyMem ( &NewTerminalContext->BaudRate, &Uart->BaudRate, sizeof (UINT64) ); CopyMem ( &NewTerminalContext->DataBits, &Uart->DataBits, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->Parity, &Uart->Parity, sizeof (UINT8) ); CopyMem ( &NewTerminalContext->StopBits, &Uart->StopBits, sizeof (UINT8) ); FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Node); if (IsUartFlowControlNode (FlowControlNode)) { HasFlowControlNode = TRUE; NewTerminalContext->FlowControl = (UINT8) ReadUnaligned32 (&FlowControlNode->FlowControlMap); } else if (NewTerminalContext->FlowControl != 0) { // // No Flow Control device path node, assumption no Flow control // NewTerminalContext->FlowControl = 0; } SerialNode = NewTerminalContext->DevicePath; SerialNode = NextDevicePathNode (SerialNode); while (!IsDevicePathEnd (SerialNode)) { if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) { // // Update following device paths according to // previous acquired uart attributes // Uart1 = (UART_DEVICE_PATH *) SerialNode; CopyMem ( &Uart1->BaudRate, &NewTerminalContext->BaudRate, sizeof (UINT64) ); CopyMem ( &Uart1->DataBits, &NewTerminalContext->DataBits, sizeof (UINT8) ); CopyMem ( &Uart1->Parity, &NewTerminalContext->Parity, sizeof (UINT8) ); CopyMem ( &Uart1->StopBits, &NewTerminalContext->StopBits, sizeof (UINT8) ); FlowControlNode = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (SerialNode); if (IsUartFlowControlNode (FlowControlNode)) { FlowControlNode->FlowControlMap = NewTerminalContext->FlowControl; } else { if (HasFlowControlNode) { mFlowControlDevicePath.FlowControlMap = NewTerminalContext->FlowControl; NewTerminalContext->DevicePath = AppendDevicePathNode ( NewTerminalContext->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) (&mFlowControlDevicePath) ); } } break; } SerialNode = NextDevicePathNode (SerialNode); } // // end while // } Node = NextDevicePathNode (Node); } // // end while // } return EFI_SUCCESS; }
/** Write 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[in] 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 CpuIoServiceWrite ( 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, IN VOID *Buffer ) { EFI_STATUS Status; UINT8 InStride; UINT8 OutStride; EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth; BOOLEAN Aligned; UINT8 *Uint8Buffer; // // Make sure the parameters are valid // 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: IoWriteFifo8 ((UINTN)Address, Count, Buffer); return EFI_SUCCESS; case EfiPeiCpuIoWidthUint16: IoWriteFifo16 ((UINTN)Address, Count, Buffer); return EFI_SUCCESS; case EfiPeiCpuIoWidthUint32: IoWriteFifo32 ((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 = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { if (OperationWidth == EfiPeiCpuIoWidthUint8) { IoWrite8 ((UINTN)Address, *Uint8Buffer); } else if (OperationWidth == EfiPeiCpuIoWidthUint16) { if (Aligned) { IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); } else { IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint32) { if (Aligned) { IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); } else { IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer)); } } } return EFI_SUCCESS; }
/** Receive response data of last command from TPM. @param[out] TpmBuffer Buffer for response data. @param[out] RespSize Response data length. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_TIMEOUT The register can't run into the expected status in time. @retval EFI_DEVICE_ERROR Unexpected device status. @retval EFI_BUFFER_TOO_SMALL Response data is too long. **/ EFI_STATUS TisPcReceive ( OUT UINT8 *TpmBuffer, OUT UINT32 *RespSize ) { EFI_STATUS Status; UINT16 BurstCount; UINT32 Index; UINT32 ResponseSize; TPM_RSP_COMMAND_HDR *ResponseHeader; // // Wait for the command completion // Status = TisPcWaitRegisterBits ( INFINEON_TPM_STS_0_ADDRESS_DEFAULT, (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA), 0, TIS_TIMEOUT_B ); if (EFI_ERROR (Status)) { Status = EFI_TIMEOUT; goto Done; } // // Read the response data header and check it // Index = 0; BurstCount = 0; while (Index < sizeof (TPM_RSP_COMMAND_HDR)) { Status = TisPcReadBurstCount (&BurstCount); if (EFI_ERROR (Status)) { Status = EFI_TIMEOUT; goto Done; } for (; BurstCount > 0 ; BurstCount--) { *(TpmBuffer + Index) = TpmReadByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT); Index++; if (Index == sizeof (TPM_RSP_COMMAND_HDR)) break; } } // // Check the response data header (tag, parasize and returncode) // ResponseHeader = (TPM_RSP_COMMAND_HDR *)TpmBuffer; if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader->tag)) != TPM_TAG_RSP_COMMAND) { Status = EFI_DEVICE_ERROR; goto Done; } ResponseSize = SwapBytes32 (ReadUnaligned32 (&ResponseHeader->paramSize)); if (ResponseSize == sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_SUCCESS; goto Done; } if (ResponseSize < sizeof (TPM_RSP_COMMAND_HDR)) { Status = EFI_DEVICE_ERROR; goto Done; } if (*RespSize < ResponseSize) { Status = EFI_BUFFER_TOO_SMALL; goto Done; } *RespSize = ResponseSize; // // Continue reading the remaining data // while (Index < ResponseSize) { for (; BurstCount > 0 ; BurstCount--) { *(TpmBuffer + Index) = TpmReadByte (INFINEON_TPM_DATA_FIFO_0_ADDRESS_DEFAULT); Index++; if (Index == ResponseSize) { Status = EFI_SUCCESS; goto Done; } } Status = TisPcReadBurstCount (&BurstCount); if (EFI_ERROR (Status) && (Index < ResponseSize)) { Status = EFI_DEVICE_ERROR; goto Done; } } Done: // // Ensure the TPM state change from "Execution" or "Completion" to "Idle/Ready" // TpmWriteByte (INFINEON_TPM_STS_0_ADDRESS_DEFAULT, TIS_PC_STS_READY); return Status; }