/** Create a HTTP_IO to access the HTTP service. It will create and configure a HTTP child handle. @param[in] Image The handle of the driver image. @param[in] Controller The handle of the controller. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. @param[in] ConfigData The HTTP_IO configuration data. @param[out] HttpIo The HTTP_IO. @retval EFI_SUCCESS The HTTP_IO is created and configured. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_UNSUPPORTED One or more of the control options are not supported in the implementation. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval Others Failed to create the HTTP_IO or configure it. **/ EFI_STATUS HttpIoCreateIo ( IN EFI_HANDLE Image, IN EFI_HANDLE Controller, IN UINT8 IpVersion, IN HTTP_IO_CONFIG_DATA *ConfigData, OUT HTTP_IO *HttpIo ) { EFI_STATUS Status; EFI_HTTP_CONFIG_DATA HttpConfigData; EFI_HTTPv4_ACCESS_POINT Http4AccessPoint; EFI_HTTPv6_ACCESS_POINT Http6AccessPoint; EFI_HTTP_PROTOCOL *Http; EFI_EVENT Event; if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) { return EFI_INVALID_PARAMETER; } if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) { return EFI_UNSUPPORTED; } ZeroMem (HttpIo, sizeof (HTTP_IO)); // // Create the HTTP child instance and get the HTTP protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiHttpServiceBindingProtocolGuid, &HttpIo->Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( HttpIo->Handle, &gEfiHttpProtocolGuid, (VOID **) &Http, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) || (Http == NULL)) { goto ON_ERROR; } // // Init the configuration data and configure the HTTP child. // HttpIo->Image = Image; HttpIo->Controller = Controller; HttpIo->IpVersion = IpVersion; HttpIo->Http = Http; ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA)); HttpConfigData.HttpVersion = HttpVersion11; HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut; if (HttpIo->IpVersion == IP_VERSION_4) { HttpConfigData.LocalAddressIsIPv6 = FALSE; Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress; Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort; IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp); IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask); HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint; } else { HttpConfigData.LocalAddressIsIPv6 = TRUE; Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort; IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp); HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint; } Status = Http->Configure (Http, &HttpConfigData); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Create events for variuos asynchronous operations. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, HttpBootCommonNotify, &HttpIo->IsTxDone, &Event ); if (EFI_ERROR (Status)) { goto ON_ERROR; } HttpIo->ReqToken.Event = Event; HttpIo->ReqToken.Message = &HttpIo->ReqMessage; Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, HttpBootCommonNotify, &HttpIo->IsRxDone, &Event ); if (EFI_ERROR (Status)) { goto ON_ERROR; } HttpIo->RspToken.Event = Event; HttpIo->RspToken.Message = &HttpIo->RspMessage; return EFI_SUCCESS; ON_ERROR: HttpIoDestroyIo (HttpIo); return Status; }
/** Function to process the OACK. It will first validate the OACK packet, then update the various negotiated parameters. @param Instance The download MTFTP session @param Packet The packet received @param Len The packet length @param Multicast Whether this packet is received as a multicast @param Completed Returns whether the download has completed. NOT used by this function. @retval EFI_DEVICE_ERROR Failed to create/start a multicast UDP child @retval EFI_TFTP_ERROR Some error happened during the process @retval EFI_SUCCESS The OACK is successfully processed. **/ EFI_STATUS Mtftp4RrqHandleOack ( IN OUT MTFTP4_PROTOCOL *Instance, IN EFI_MTFTP4_PACKET *Packet, IN UINT32 Len, IN BOOLEAN Multicast, OUT BOOLEAN *Completed ) { MTFTP4_OPTION Reply; EFI_STATUS Status; INTN Expected; EFI_UDP4_PROTOCOL *Udp4; *Completed = FALSE; // // If already started the master download, don't change the // setting. Master download always succeeds. // Expected = Mtftp4GetNextBlockNum (&Instance->Blocks); ASSERT (Expected != -1); if (Instance->Master && (Expected != 1)) { return EFI_SUCCESS; } // // Parse and validate the options from server // ZeroMem (&Reply, sizeof (MTFTP4_OPTION)); Status = Mtftp4ParseOptionOack (Packet, Len, &Reply); if (EFI_ERROR (Status) || !Mtftp4RrqOackValid (Instance, &Reply, &Instance->RequestOption)) { // // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES. // if (Status != EFI_OUT_OF_RESOURCES) { Mtftp4SendError ( Instance, EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION, (UINT8 *) "Mal-formated OACK packet" ); } return EFI_TFTP_ERROR; } if ((Reply.Exist & MTFTP4_MCAST_EXIST) != 0) { // // Save the multicast info. Always update the Master, only update the // multicast IP address, block size, timeoute at the first time. If IP // address is updated, create a UDP child to receive the multicast. // Instance->Master = Reply.Master; if (Instance->McastIp == 0) { if ((Reply.McastIp == 0) || (Reply.McastPort == 0)) { Mtftp4SendError ( Instance, EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION, (UINT8 *) "Illegal multicast setting" ); return EFI_TFTP_ERROR; } // // Create a UDP child then start receive the multicast from it. // Instance->McastIp = Reply.McastIp; Instance->McastPort = Reply.McastPort; if (Instance->McastUdpPort == NULL) { Instance->McastUdpPort = UdpIoCreateIo ( Instance->Service->Controller, Instance->Service->Image, Mtftp4RrqConfigMcastPort, UDP_IO_UDP4_VERSION, Instance ); if (Instance->McastUdpPort != NULL) { Status = gBS->OpenProtocol ( Instance->McastUdpPort->UdpHandle, &gEfiUdp4ProtocolGuid, (VOID **) &Udp4, Instance->Service->Image, Instance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { UdpIoFreeIo (Instance->McastUdpPort); Instance->McastUdpPort = NULL; return EFI_DEVICE_ERROR; } } } if (Instance->McastUdpPort == NULL) { return EFI_DEVICE_ERROR; } Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0); if (EFI_ERROR (Status)) { Mtftp4SendError ( Instance, EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION, (UINT8 *) "Failed to create socket to receive multicast packet" ); return Status; } // // Update the parameters used. // if (Reply.BlkSize != 0) { Instance->BlkSize = Reply.BlkSize; } if (Reply.Timeout != 0) { Instance->Timeout = Reply.Timeout; } } } else { Instance->Master = TRUE; if (Reply.BlkSize != 0) { Instance->BlkSize = Reply.BlkSize; } if (Reply.Timeout != 0) { Instance->Timeout = Reply.Timeout; } } // // Send an ACK to (Expected - 1) which is 0 for unicast download, // or tell the server we want to receive the Expected block. // return Mtftp4RrqSendAck (Instance, (UINT16) (Expected - 1)); }
/** 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]); PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint32, NVME_BAR, NVME_SQTDBL_OFFSET(QueueId, Private->Cap.Dstrd), 1, &Data ); // // 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; 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(); } } if ((Private->CqHdbl[QueueId].Cqh ^= 1) == 0) { Private->Pt[QueueId] ^= 1; } Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]); 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; }
/** Output pixels in "1 bit per pixel" format to an image. This is a internal function. @param Image Points to the image which will store the pixels. @param Data Stores the value of output pixels, 0 or 1. @param PaletteInfo PaletteInfo which stores the color of the output pixels. First entry corresponds to color 0 and second one to color 1. **/ VOID Output1bitPixel ( IN OUT EFI_IMAGE_INPUT *Image, IN UINT8 *Data, IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo ) { UINT16 Xpos; UINT16 Ypos; UINTN OffsetY; UINT8 Index; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr; EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2]; EFI_HII_IMAGE_PALETTE_INFO *Palette; UINT16 PaletteSize; UINT8 Byte; ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL); BitMapPtr = Image->Bitmap; // // First entry corresponds to color 0 and second entry corresponds to color 1. // CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16)); PaletteSize += sizeof (UINT16); Palette = AllocateZeroPool (PaletteSize); ASSERT (Palette != NULL); CopyMem (Palette, PaletteInfo, PaletteSize); ZeroMem (PaletteValue, sizeof (PaletteValue)); CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1); CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1); FreePool (Palette); // // Convert the pixel from one bit to corresponding color. // for (Ypos = 0; Ypos < Image->Height; Ypos++) { OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos); // // All bits in these bytes are meaningful // for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) { Byte = *(Data + OffsetY + Xpos); for (Index = 0; Index < 8; Index++) { if ((Byte & (1 << Index)) != 0) { BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1]; } else { BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0]; } } } if (Image->Width % 8 != 0) { // // Padding bits in this byte should be ignored. // Byte = *(Data + OffsetY + Xpos); for (Index = 0; Index < Image->Width % 8; Index++) { if ((Byte & (1 << (8 - Index - 1))) != 0) { BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1]; } else { BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0]; } } } } }
/** Create 4G PageTable in SMRAM. @param ExtraPages Additional page numbers besides for 4G memory @return PageTable Address **/ UINT32 Gen4GPageTable ( IN UINTN ExtraPages ) { VOID *PageTable; UINTN Index; UINT64 *Pte; UINTN PagesNeeded; UINTN Low2MBoundary; UINTN High2MBoundary; UINTN Pages; UINTN GuardPage; UINT64 *Pdpte; UINTN PageIndex; UINTN PageAddress; Low2MBoundary = 0; High2MBoundary = 0; PagesNeeded = 0; if (FeaturePcdGet (PcdCpuSmmStackGuard)) { // // Add one more page for known good stack, then find the lower 2MB aligned address. // Low2MBoundary = (mSmmStackArrayBase + EFI_PAGE_SIZE) & ~(SIZE_2MB-1); // // Add two more pages for known good stack and stack guard page, // then find the lower 2MB aligned address. // High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1); PagesNeeded = ((High2MBoundary - Low2MBoundary) / SIZE_2MB) + 1; } // // Allocate the page table // PageTable = AllocatePages (ExtraPages + 5 + PagesNeeded); ASSERT (PageTable != NULL); PageTable = (VOID *)((UINTN)PageTable + EFI_PAGES_TO_SIZE (ExtraPages)); Pte = (UINT64*)PageTable; // // Zero out all page table entries first // ZeroMem (Pte, EFI_PAGES_TO_SIZE (1)); // // Set Page Directory Pointers // for (Index = 0; Index < 4; Index++) { Pte[Index] = (UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1) + IA32_PG_P; } Pte += EFI_PAGE_SIZE / sizeof (*Pte); // // Fill in Page Directory Entries // for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) { Pte[Index] = (Index << 21) + IA32_PG_PS + IA32_PG_RW + IA32_PG_P; } if (FeaturePcdGet (PcdCpuSmmStackGuard)) { Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5); GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE; Pdpte = (UINT64*)PageTable; for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) { Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~(EFI_PAGE_SIZE - 1)); Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages + IA32_PG_RW + IA32_PG_P; // // Fill in Page Table Entries // Pte = (UINT64*)Pages; PageAddress = PageIndex; for (Index = 0; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) { if (PageAddress == GuardPage) { // // Mark the guard page as non-present // Pte[Index] = PageAddress; GuardPage += mSmmStackSize; if (GuardPage > mSmmStackArrayEnd) { GuardPage = 0; } } else { Pte[Index] = PageAddress + IA32_PG_RW + IA32_PG_P; } PageAddress+= EFI_PAGE_SIZE; } Pages += EFI_PAGE_SIZE; } } return (UINT32)(UINTN)PageTable; }
/** Check and execute the pending TPM request and Lock TPM. The TPM request may come from OS or BIOS. This API will display request information and wait for user confirmation if TPM request exists. The TPM request will be sent to TPM device after the TPM request is confirmed, and one or more reset may be required to make TPM request to take effect. At last, it will lock TPM to prevent TPM state change by malware. This API should be invoked after console in and console out are all ready as they are required to display request information and get user input to confirm the request. This API should also be invoked as early as possible as TPM is locked in this function. **/ VOID EFIAPI TcgPhysicalPresenceLibProcessRequest ( VOID ) { EFI_STATUS Status; BOOLEAN LifetimeLock; BOOLEAN CmdEnable; UINTN DataSize; EFI_PHYSICAL_PRESENCE TcgPpData; EFI_TCG_PROTOCOL *TcgProtocol; EDKII_VARIABLE_LOCK_PROTOCOL *VariableLockProtocol; UINT8 PpiFlags; Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol); if (EFI_ERROR (Status)) { return ; } // // Initialize physical presence flags. // DataSize = sizeof (UINT8); Status = gRT->GetVariable ( PHYSICAL_PRESENCE_FLAGS_VARIABLE, &gEfiPhysicalPresenceGuid, NULL, &DataSize, &PpiFlags ); if (EFI_ERROR (Status)) { if (Status == EFI_NOT_FOUND) { PpiFlags = FLAG_NO_PPI_PROVISION; Status = gRT->SetVariable ( PHYSICAL_PRESENCE_FLAGS_VARIABLE, &gEfiPhysicalPresenceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (UINT8), &PpiFlags ); } ASSERT_EFI_ERROR (Status); } DEBUG ((EFI_D_ERROR, "[TPM] PpiFlags = %x, Status = %r\n", PpiFlags, Status)); // // This flags variable controls whether physical presence is required for TPM command. // It should be protected from malicious software. We set it as read-only variable here. // Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol); if (!EFI_ERROR (Status)) { Status = VariableLockProtocol->RequestToLock ( VariableLockProtocol, PHYSICAL_PRESENCE_FLAGS_VARIABLE, &gEfiPhysicalPresenceGuid ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "[TPM] Error when lock variable %s, Status = %r\n", PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status)); ASSERT_EFI_ERROR (Status); } } // // Initialize physical presence variable. // DataSize = sizeof (EFI_PHYSICAL_PRESENCE); Status = gRT->GetVariable ( PHYSICAL_PRESENCE_VARIABLE, &gEfiPhysicalPresenceGuid, NULL, &DataSize, &TcgPpData ); if (EFI_ERROR (Status)) { if (Status == EFI_NOT_FOUND) { ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData)); DataSize = sizeof (EFI_PHYSICAL_PRESENCE); Status = gRT->SetVariable ( PHYSICAL_PRESENCE_VARIABLE, &gEfiPhysicalPresenceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, DataSize, &TcgPpData ); } ASSERT_EFI_ERROR (Status); } DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", PpiFlags, TcgPpData.PPRequest)); if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) { // // No operation request // return; } Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable); if (EFI_ERROR (Status)) { return ; } if (!CmdEnable) { if (LifetimeLock) { // // physicalPresenceCMDEnable is locked, can't execute physical presence command. // return ; } Status = TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_CMD_ENABLE); if (EFI_ERROR (Status)) { return ; } } // // Set operator physical presence flags // TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_PRESENT); // // Execute pending TPM request. // ExecutePendingTpmRequest (TcgProtocol, &TcgPpData, PpiFlags); DEBUG ((EFI_D_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse)); // // Lock physical presence. // TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK); }
/** Function to read a single line (up to but not including the \n) from a file. If the position upon start is 0, then the Ascii Boolean will be set. This should be maintained and not changed for all operations with the same file. The function will not return the \r and \n character in buffer. When an empty line is read a CHAR_NULL character will be returned in buffer. @param[in] Handle FileHandle to read from. @param[in, out] Buffer The pointer to buffer to read into. @param[in, out] Size The pointer to number of bytes in Buffer. @param[in] Truncate If the buffer is large enough, this has no effect. If the buffer is is too small and Truncate is TRUE, the line will be truncated. If the buffer is is too small and Truncate is FALSE, then no read will occur. @param[in, out] Ascii Boolean value for indicating whether the file is Ascii (TRUE) or UCS2 (FALSE). @retval EFI_SUCCESS The operation was successful. The line is stored in Buffer. @retval EFI_INVALID_PARAMETER Handle was NULL. @retval EFI_INVALID_PARAMETER Size was NULL. @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line. Size was updated to the minimum space required. @sa FileHandleRead **/ EFI_STATUS EFIAPI FileHandleReadLine( IN EFI_FILE_HANDLE Handle, IN OUT CHAR16 *Buffer, IN OUT UINTN *Size, IN BOOLEAN Truncate, IN OUT BOOLEAN *Ascii ) { EFI_STATUS Status; CHAR16 CharBuffer; UINT64 FileSize; UINTN CharSize; UINTN CountSoFar; UINTN CrCount; UINT64 OriginalFilePosition; if (Handle == NULL ||Size == NULL ||(Buffer==NULL&&*Size!=0) ){ return (EFI_INVALID_PARAMETER); } if (Buffer != NULL && *Size != 0) { *Buffer = CHAR_NULL; } Status = FileHandleGetSize (Handle, &FileSize); if (EFI_ERROR (Status)) { return Status; } else if (FileSize == 0) { *Ascii = TRUE; return EFI_SUCCESS; } FileHandleGetPosition(Handle, &OriginalFilePosition); if (OriginalFilePosition == 0) { CharSize = sizeof(CHAR16); Status = FileHandleRead(Handle, &CharSize, &CharBuffer); ASSERT_EFI_ERROR(Status); if (CharBuffer == gUnicodeFileTag) { *Ascii = FALSE; } else { *Ascii = TRUE; FileHandleSetPosition(Handle, OriginalFilePosition); } } CrCount = 0; for (CountSoFar = 0;;CountSoFar++){ CharBuffer = 0; if (*Ascii) { CharSize = sizeof(CHAR8); } else { CharSize = sizeof(CHAR16); } Status = FileHandleRead(Handle, &CharSize, &CharBuffer); if ( EFI_ERROR(Status) || CharSize == 0 || (CharBuffer == L'\n' && !(*Ascii)) || (CharBuffer == '\n' && *Ascii) ){ break; } else if ( (CharBuffer == L'\r' && !(*Ascii)) || (CharBuffer == '\r' && *Ascii) ) { CrCount++; continue; } // // if we have space save it... // if ((CountSoFar+1-CrCount)*sizeof(CHAR16) < *Size){ ASSERT(Buffer != NULL); ((CHAR16*)Buffer)[CountSoFar-CrCount] = CharBuffer; ((CHAR16*)Buffer)[CountSoFar+1-CrCount] = CHAR_NULL; } } // // if we ran out of space tell when... // if ((CountSoFar+1-CrCount)*sizeof(CHAR16) > *Size){ *Size = (CountSoFar+1-CrCount)*sizeof(CHAR16); if (!Truncate) { if (Buffer != NULL && *Size != 0) { ZeroMem(Buffer, *Size); } FileHandleSetPosition(Handle, OriginalFilePosition); return (EFI_BUFFER_TOO_SMALL); } else { DEBUG((DEBUG_WARN, "The line was truncated in FileHandleReadLine")); return (EFI_SUCCESS); } } return (Status); }
/** The entry point for 96BoardsDxe driver. @param[in] ImageHandle The image handle of the driver. @param[in] SystemTable The system table. @retval EFI_ALREADY_STARTED The driver already exists in system. @retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of resources. @retval EFI_SUCCES All the related protocols are installed on the driver. **/ EFI_STATUS EFIAPI EntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; NINETY_SIX_BOARDS_CONFIG_DATA ConfigData; UINTN BufferSize; // // Get the current config settings from the EFI variable. // BufferSize = sizeof (ConfigData); Status = gRT->GetVariable (NINETY_SIX_BOARDS_CONFIG_VARIABLE_NAME, &g96BoardsFormsetGuid, NULL, &BufferSize, &ConfigData); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a: no config data found\n", __FUNCTION__)); ConfigData.MezzanineType = MEZZANINE_NONE; } if (!EFI_ERROR (Status) && ConfigData.MezzanineType >= MEZZANINE_MAX) { DEBUG ((DEBUG_WARN, "%a: invalid value for %s, defaulting to MEZZANINE_NONE\n", __FUNCTION__, NINETY_SIX_BOARDS_CONFIG_VARIABLE_NAME)); ConfigData.MezzanineType = MEZZANINE_NONE; Status = EFI_INVALID_PARAMETER; // trigger setvar below } // // Write the newly selected value back to the variable store. // if (EFI_ERROR (Status)) { ZeroMem (&ConfigData.Reserved, sizeof (ConfigData.Reserved)); Status = gRT->SetVariable (NINETY_SIX_BOARDS_CONFIG_VARIABLE_NAME, &g96BoardsFormsetGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (ConfigData), &ConfigData); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: gRT->SetVariable () failed - %r\n", __FUNCTION__, Status)); return Status; } } switch (ConfigData.MezzanineType) { case MEZZANINE_SECURE96: mLsConnector.MezzanineType = MezzanineSecure96; break; default: mLsConnector.MezzanineType = MezzanineUnknown; } Status = gBS->InstallProtocolInterface (&ImageHandle, &g96BoardsLsConnectorProtocolGuid, EFI_NATIVE_INTERFACE, &mLsConnector); if (EFI_ERROR (Status)) { return Status; } Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, ApplyDeviceTreeOverlay, NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent); ASSERT_EFI_ERROR (Status); return InstallHiiPages (); }
EFI_STATUS EFIAPI InitializeAttrib ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) /*++ Routine Description: Command entry point. Parses command line arguments and calls internal function to perform actual action. Arguments: ImageHandle The image handle. SystemTable The system table. Returns: EFI_SUCCESS - Command completed successfully EFI_INVALID_PARAMETER - Command usage error Other value - Unknown error --*/ { UINTN Index; EFI_LIST_ENTRY FileList; EFI_LIST_ENTRY *Link; SHELL_FILE_ARG *Arg; UINT64 Remove; UINT64 Add; EFI_STATUS Status; SHELL_VAR_CHECK_CODE RetCode; CHAR16 *Useful; SHELL_ARG_LIST *Item; SHELL_VAR_CHECK_PACKAGE ChkPck; ZeroMem (&ChkPck, sizeof (SHELL_VAR_CHECK_PACKAGE)); // // We are no being installed as an internal command driver, initialize // as an nshell app and run // EFI_SHELL_APP_INIT (ImageHandle, SystemTable); // // Enable tab key which can pause the output // EnableOutputTabPause(); Status = LibFilterNullArgs (); if (EFI_ERROR (Status)) { return Status; } // // Register our string package with HII and return the handle to it. // If previously registered we will simply receive the handle // EFI_SHELL_STR_INIT (HiiHandle, STRING_ARRAY_NAME, EfiAttribGuid); if (!EFI_PROPER_VERSION (0, 99)) { PrintToken ( STRING_TOKEN (STR_SHELLENV_GNC_COMMAND_NOT_SUPPORT), HiiHandle, L"attrib", EFI_VERSION_0_99 ); Status = EFI_UNSUPPORTED; goto Quit; } RetCode = LibCheckVariables (SI, AttribCheckList, &ChkPck, &Useful); if (VarCheckOk != RetCode) { switch (RetCode) { case VarCheckConflict: PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_FLAG_CONFLICT), HiiHandle, L"attrib", Useful); break; case VarCheckDuplicate: PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_DUP_FLAG), HiiHandle, L"attrib", Useful); break; case VarCheckUnknown: PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_UNKNOWN_FLAG), HiiHandle, L"attrib", Useful); break; default: break; } Status = EFI_INVALID_PARAMETER; goto Quit; } // // Out put help. // if (LibCheckVarGetFlag (&ChkPck, L"-b") != NULL) { EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF); } if (LibCheckVarGetFlag (&ChkPck, L"-?") != NULL) { if (IS_OLD_SHELL) { PrintToken (STRING_TOKEN (STR_NO_HELP), HiiHandle); goto Quit; } if (ChkPck.ValueCount > 0 || ChkPck.FlagCount > 2 || (2 == ChkPck.FlagCount && !LibCheckVarGetFlag (&ChkPck, L"-b")) ) { PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_MANY), HiiHandle, L"attrib"); Status = EFI_INVALID_PARAMETER; } else { PrintToken (STRING_TOKEN (STR_ATTRIB_VERBOSE_HELP), HiiHandle); Status = EFI_SUCCESS; } goto Quit; } // // Local Variable Initializations // InitializeListHead (&FileList); Link = NULL; Arg = NULL; Remove = 0; Add = 0; // // Parse command line arguments // Item = GetFirstFlag (&ChkPck); for (Index = 0; Index < ChkPck.FlagCount; Index += 1) { if (Item->FlagStr[0] == '-') { // // Attributes to remove // Status = AttribSet (&Item->FlagStr[1], &Remove); if (EFI_ERROR (Status)) { PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"attrib", Item->FlagStr); goto Done; } } else if (Item->FlagStr[0] == '+') { // // Attributes to Add // Status = AttribSet (&Item->FlagStr[1], &Add); if (EFI_ERROR (Status)) { PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"attrib", Item->FlagStr); goto Done; } } else { // // we should never get here // ASSERT (FALSE); } Item = GetNextArg (Item); } Item = GetFirstArg (&ChkPck); for (Index = 0; Index < ChkPck.ValueCount; Index += 1) { Status = ShellFileMetaArg (Item->VarStr, &FileList); if (EFI_ERROR (Status)) { PrintToken (STRING_TOKEN (STR_ATTRIB_CANNOT_OPEN), HiiHandle, L"attrib", Item->VarStr, Status); goto Done; } Item = GetNextArg (Item); } // // if no file is specified, get the whole directory // if (IsListEmpty (&FileList)) { Status = ShellFileMetaArg (L"*", &FileList); if (EFI_ERROR (Status)) { PrintToken (STRING_TOKEN (STR_ATTRIB_CANNOT_OPEN_DIR), HiiHandle, L"attrib", Status); goto Done; } } ShellDelDupFileArg (&FileList); // // Attrib each file // for (Link = FileList.Flink; Link != &FileList; Link = Link->Flink) { // // Break the execution? // if (GetExecutionBreak ()) { goto Done; } Arg = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE); Status = AttribFile (Arg, Remove, Add); } Done: ShellFreeFileList (&FileList); Quit: LibCheckVarFreeVarList (&ChkPck); LibUnInitializeStrings (); return Status; }
/** Initialize debug agent. This function is used to set up debug enviroment for DXE phase. If this function is called by DXE Core, Context must be the pointer to HOB list which will be used to get GUIDed HOB. It will enable interrupt to support break-in feature. If this function is called by DXE module, Context must be NULL. It will enable interrupt to support break-in feature. @param[in] InitFlag Init flag is used to decide initialize process. @param[in] Context Context needed according to InitFlag. @param[in] Function Continue function called by debug agent library; it was optional. **/ VOID EFIAPI InitializeDebugAgent ( IN UINT32 InitFlag, IN VOID *Context, OPTIONAL IN DEBUG_AGENT_CONTINUE Function OPTIONAL ) { DEBUG_AGENT_MAILBOX *Mailbox; IA32_DESCRIPTOR Idtr; UINT16 IdtEntryCount; BOOLEAN InterruptStatus; if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE && InitFlag != DEBUG_AGENT_INIT_S3 && InitFlag != DEBUG_AGENT_INIT_DXE_AP) { return; } // // Save and disable original interrupt status // InterruptStatus = SaveAndDisableInterrupts (); if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) { // // Try to get Mailbox from GUIDed HOB. // mDxeCoreFlag = TRUE; Mailbox = GetMailboxFromHob (Context); // // Clear Break CPU index value // mDebugMpContext.BreakAtCpuIndex = (UINT32) -1; } else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) { EnableInterrupts (); return; } else { // // If it is in S3 path, needn't to install configuration table. // Mailbox = NULL; } if (Mailbox != NULL) { // // If Mailbox exists, copy it into one global variable. // CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX)); } else { // // If Mailbox not exists, used the local Mailbox. // ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX)); } mMailboxPointer = &mMailbox; // // Get original IDT address and size. // AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr); IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)); if (IdtEntryCount < 33) { Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1); Idtr.Base = (UINTN) &mIdtEntryTable; ZeroMem (&mIdtEntryTable, Idtr.Limit + 1); AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr); } // // Initialize the IDT table entries to support source level debug. // InitializeDebugIdt (); // // Initialize debug communication port // mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailbox.DebugPortHandle, NULL); InitializeSpinLock (&mDebugMpContext.MpContextSpinLock); InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock); if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) { // // Initialize Debug Timer hardware and enable interrupt. // InitializeDebugTimer (); EnableInterrupts (); return; } else { // // Disable Debug Timer interrupt in S3 path. // SaveAndSetDebugTimerInterrupt (FALSE); // // Restore interrupt state. // SetInterruptState (InterruptStatus); } }
/** Relocate this image under 4G memory for IPF. @param ImageHandle Handle of driver image. @param SystemTable Pointer to system table. @retval EFI_SUCCESS Image successfully relocated. @retval EFI_ABORTED Failed to relocate image. **/ EFI_STATUS RelocateImageUnder4GIfNeeded ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; UINTN NumberOfPages; EFI_PHYSICAL_ADDRESS LoadedImageBase; PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; EFI_PHYSICAL_ADDRESS MemoryAddress; EFI_HANDLE NewImageHandle; Status = gBS->HandleProtocol ( ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedImage ); if (!EFI_ERROR (Status)) { LoadedImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImage->ImageBase; if (LoadedImageBase > 0xffffffff) { NumberOfPages = (UINTN) (DivU64x32(LoadedImage->ImageSize, EFI_PAGE_SIZE) + 1); // // Allocate buffer below 4GB here // Status = AllocateLegacyMemory ( AllocateMaxAddress, 0x7FFFFFFF, NumberOfPages, // do we have to convert this to pages?? &MemoryAddress ); if (EFI_ERROR (Status)) { return Status; } ZeroMem (&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); ImageContext.Handle = (VOID *)(UINTN)LoadedImageBase; ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; // // Get information about the image being loaded // Status = PeCoffLoaderGetImageInfo (&ImageContext); if (EFI_ERROR (Status)) { return Status; } ImageContext.ImageAddress = (PHYSICAL_ADDRESS)MemoryAddress; // // Align buffer on section boundry // ImageContext.ImageAddress += ImageContext.SectionAlignment - 1; ImageContext.ImageAddress &= ~((PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1); // // Load the image to our new buffer // Status = PeCoffLoaderLoadImage (&ImageContext); if (EFI_ERROR (Status)) { gBS->FreePages (MemoryAddress, NumberOfPages); return Status; } // // Relocate the image in our new buffer // Status = PeCoffLoaderRelocateImage (&ImageContext); if (EFI_ERROR (Status)) { gBS->FreePages (MemoryAddress, NumberOfPages); return Status; } // // Create a new handle with gEfiCallerIdGuid to be used as the ImageHandle fore the reloaded image // NewImageHandle = NULL; Status = gBS->InstallProtocolInterface ( &NewImageHandle, &gEfiCallerIdGuid, EFI_NATIVE_INTERFACE, NULL ); // // Flush the instruction cache so the image data is written before we execute it // InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable); if (EFI_ERROR (Status)) { gBS->FreePages (MemoryAddress, NumberOfPages); return Status; } // // return error directly the BS will unload this image // return EFI_ABORTED; } } return EFI_SUCCESS; }
/** This routine is invoked by main entry of PeiMain module during transition from SEC to PEI. After switching stack in the PEI core, it will restart with the old core data. @param SecCoreDataPtr Points to a data structure containing information about the PEI core's operating environment, such as the size and location of temporary RAM, the stack location and the BFV location. @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. An empty PPI list consists of a single descriptor with the end-tag EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such that both the PEI Foundation and any modules can leverage the associated service calls and/or code in these early PPIs @param Data Pointer to old core data that is used to initialize the core's data areas. If NULL, it is first PeiCore entering. **/ VOID EFIAPI PeiCore ( IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreDataPtr, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, IN VOID *Data ) { PEI_CORE_INSTANCE PrivateData; EFI_SEC_PEI_HAND_OFF *SecCoreData; EFI_SEC_PEI_HAND_OFF NewSecCoreData; EFI_STATUS Status; PEI_CORE_TEMP_POINTERS TempPtr; PEI_CORE_INSTANCE *OldCoreData; EFI_PEI_CPU_IO_PPI *CpuIo; EFI_PEI_PCI_CFG2_PPI *PciCfg; EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable; EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi; UINTN Index; // // Retrieve context passed into PEI Core // OldCoreData = (PEI_CORE_INSTANCE *) Data; SecCoreData = (EFI_SEC_PEI_HAND_OFF *) SecCoreDataPtr; // // Perform PEI Core phase specific actions. // if (OldCoreData == NULL) { // // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available. // ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE)); PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs)); } else { // // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet. // if (OldCoreData->ShadowedPeiCore == NULL) { // // Fixup the PeiCore's private data // OldCoreData->Ps = &OldCoreData->ServiceTableShadow; OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo; if (OldCoreData->HeapOffsetPositive) { OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset); OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset); OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset); OldCoreData->PpiData.PpiListPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs + OldCoreData->HeapOffset); OldCoreData->Fv = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv + OldCoreData->HeapOffset); for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) { OldCoreData->Fv[Index].PeimState = (UINT8 *) OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset; OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset); } OldCoreData->FileGuid = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid + OldCoreData->HeapOffset); OldCoreData->FileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles + OldCoreData->HeapOffset); } else { OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset); OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo - OldCoreData->HeapOffset); OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset); OldCoreData->PpiData.PpiListPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs - OldCoreData->HeapOffset); OldCoreData->Fv = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv - OldCoreData->HeapOffset); for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) { OldCoreData->Fv[Index].PeimState = (UINT8 *) OldCoreData->Fv[Index].PeimState - OldCoreData->HeapOffset; OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset); } OldCoreData->FileGuid = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid - OldCoreData->HeapOffset); OldCoreData->FileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles - OldCoreData->HeapOffset); } // // Initialize libraries that the PEI Core is linked against // ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps); // // Fixup for PeiService's address // SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps); // // Update HandOffHob for new installed permenent memory // HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable; if (OldCoreData->HeapOffsetPositive) { HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset; } else { HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset; } HandoffInformationTable->EfiMemoryTop = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength; HandoffInformationTable->EfiMemoryBottom = OldCoreData->PhysicalMemoryBegin; HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop; HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER); // // We need convert the PPI descriptor's pointer // ConvertPpiPointers (SecCoreData, OldCoreData); // // After the whole temporary memory is migrated, then we can allocate page in // permenent memory. // OldCoreData->PeiMemoryInstalled = TRUE; // // Indicate that PeiCore reenter // OldCoreData->PeimDispatcherReenter = TRUE; if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { // // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array. // Every bit in the array indicate the status of the corresponding memory page available or not // OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64)); } // // Shadow PEI Core. When permanent memory is avaiable, shadow // PEI Core and PEIMs to get high performance. // OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore; if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot)) || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) { OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData); } // // PEI Core has now been shadowed to memory. Restart PEI Core in memory. // OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData); // // Should never reach here. // ASSERT (FALSE); CpuDeadLoop(); }
/** * Get file information * * @v This File handle * @v Type Type of information * @v Len Buffer size * @v Data Buffer * @ret Status EFI status code */ static EFI_STATUS EFIAPI FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data) { EFI_STATUS Status; EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile); EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *) Data; EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data; CHAR16 GuidString[36]; EFI_TIME Time; CHAR8* label; PrintInfo(L"GetInfo(%llx|'%s', %d) %s\n", (UINT64) This, FileName(File), *Len, File->IsDir?L"<DIR>":L""); /* Determine information to return */ if (CompareMem(Type, &GenericFileInfo, sizeof(*Type)) == 0) { /* Fill file information */ PrintExtra(L"Get regular file information\n"); if (*Len < MINIMUM_INFO_LENGTH) { *Len = MINIMUM_INFO_LENGTH; return EFI_BUFFER_TOO_SMALL; } ZeroMem(Data, sizeof(EFI_FILE_INFO)); Info->Attribute = EFI_FILE_READ_ONLY; GrubTimeToEfiTime(File->Mtime, &Time); CopyMem(&Info->CreateTime, &Time, sizeof(Time)); CopyMem(&Info->LastAccessTime, &Time, sizeof(Time)); CopyMem(&Info->ModificationTime, &Time, sizeof(Time)); if (File->IsDir) { Info->Attribute |= EFI_FILE_DIRECTORY; } else { Info->FileSize = GrubGetFileSize(File); Info->PhysicalSize = GrubGetFileSize(File); } Status = Utf8ToUtf16NoAlloc(File->basename, Info->FileName, (INTN)(Info->Size - sizeof(EFI_FILE_INFO))); if (EFI_ERROR(Status)) { if (Status != EFI_BUFFER_TOO_SMALL) PrintStatusError(Status, L"Could not convert basename to UTF-8"); return Status; } /* The Info struct size already accounts for the extra NUL */ Info->Size = sizeof(EFI_FILE_INFO) + StrLen(Info->FileName) * sizeof(CHAR16); return EFI_SUCCESS; } else if (CompareMem(Type, &FileSystemInfo, sizeof(*Type)) == 0) { /* Get file system information */ PrintExtra(L"Get file system information\n"); if (*Len < MINIMUM_FS_INFO_LENGTH) { *Len = MINIMUM_FS_INFO_LENGTH; return EFI_BUFFER_TOO_SMALL; } ZeroMem(Data, sizeof(EFI_FILE_INFO)); FSInfo->Size = *Len; FSInfo->ReadOnly = 1; /* NB: This should really be cluster size, but we don't have access to that */ FSInfo->BlockSize = File->FileSystem->BlockIo->Media->BlockSize; if (FSInfo->BlockSize == 0) { PrintWarning(L"Corrected Media BlockSize\n"); FSInfo->BlockSize = 512; } FSInfo->VolumeSize = (File->FileSystem->BlockIo->Media->LastBlock + 1) * FSInfo->BlockSize; /* No idea if we can easily get this for GRUB, and the device is RO anyway */ FSInfo->FreeSpace = 0; Status = GrubLabel(File, &label); if (EFI_ERROR(Status)) { PrintStatusError(Status, L"Could not read disk label"); } else { Status = Utf8ToUtf16NoAlloc(label, FSInfo->VolumeLabel, (INTN)(FSInfo->Size - sizeof(EFI_FILE_SYSTEM_INFO))); if (EFI_ERROR(Status)) { if (Status != EFI_BUFFER_TOO_SMALL) PrintStatusError(Status, L"Could not convert label to UTF-8"); return Status; } Info->Size = sizeof(EFI_FILE_SYSTEM_INFO) + StrLen(FSInfo->VolumeLabel) * sizeof(CHAR16); } return EFI_SUCCESS; } else { GuidToString(GuidString, Type); PrintError(L"'%s': Cannot get information of type %s\n", FileName(File), GuidString); return EFI_UNSUPPORTED; } }
/** * Read directory entry * * @v file EFI file * @v Len Length to read * @v Data Data buffer * @ret Status EFI status code */ static EFI_STATUS FileReadDir(EFI_GRUB_FILE *File, UINTN *Len, VOID *Data) { EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data; EFI_STATUS Status; /* We temporarily repurpose the FileSize as a *signed* entry index */ INT64 *Index = (INT64 *) &Info->FileSize; /* And PhysicalSize as a pointer to our filename */ CHAR8 **basename = (CHAR8 **) &Info->PhysicalSize; CHAR8 path[MAX_PATH]; EFI_GRUB_FILE *TmpFile = NULL; INTN len; /* Unless we can fit our maximum size, forget it */ if (*Len < MINIMUM_INFO_LENGTH) { *Len = MINIMUM_INFO_LENGTH; return EFI_BUFFER_TOO_SMALL; } /* Populate our Info template */ ZeroMem(Data, *Len); Info->Size = *Len; *Index = File->DirIndex; strcpya(path, File->path); len = strlena(path); if (path[len-1] != '/') path[len++] = '/'; *basename = &path[len]; /* Invoke GRUB's directory listing */ Status = GrubDir(File, File->path, DirHook, Data); if (*Index >= 0) { /* No more entries */ *Len = 0; return EFI_SUCCESS; } if (EFI_ERROR(Status)) { PrintStatusError(Status, L"Directory listing failed"); return Status; } /* Our Index/FileSize must be reset */ Info->FileSize = 0; Info->PhysicalSize = 0; /* For regular files, we still need to fill the size */ if (!(Info->Attribute & EFI_FILE_DIRECTORY)) { /* Open the file and read its size */ Status = GrubCreateFile(&TmpFile, File->FileSystem); if (EFI_ERROR(Status)) { PrintStatusError(Status, L"Unable to create temporary file"); return Status; } TmpFile->path = path; Status = GrubOpen(TmpFile); if (EFI_ERROR(Status)) { // TODO: EFI_NO_MAPPING is returned for links... PrintStatusError(Status, L"Unable to obtain the size of '%s'", Info->FileName); /* Non fatal error */ } else { Info->FileSize = GrubGetFileSize(TmpFile); Info->PhysicalSize = GrubGetFileSize(TmpFile); GrubClose(TmpFile); } GrubDestroyFile(TmpFile); } *Len = (UINTN) Info->Size; /* Advance to the next entry */ File->DirIndex++; // PrintInfo(L" Entry[%d]: '%s' %s\n", File->DirIndex-1, Info->FileName, // (Info->Attribute&EFI_FILE_DIRECTORY)?L"<DIR>":L""); return EFI_SUCCESS; }
EFI_STATUS CreateTimeBasedPayload ( IN OUT UINTN *DataSize, IN OUT UINT8 **Data ) { EFI_STATUS Status; UINT8 *NewData; UINT8 *Payload; UINTN PayloadSize; EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; UINTN DescriptorSize; EFI_TIME Time; EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID; if (Data == NULL || DataSize == NULL) { return EFI_INVALID_PARAMETER; } // // In Setup mode or Custom mode, the variable does not need to be signed but the // parameters to the SetVariable() call still need to be prepared as authenticated // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate // data in it. // Payload = *Data; PayloadSize = *DataSize; DescriptorSize = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); if (NewData == NULL) { return EFI_OUT_OF_RESOURCES; } if ((Payload != NULL) && (PayloadSize != 0)) { CopyMem (NewData + DescriptorSize, Payload, PayloadSize); } DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); ZeroMem (&Time, sizeof (EFI_TIME)); Status = RT->GetTime(&Time, NULL); if (EFI_ERROR (Status)) { FreePool(NewData); return Status; } Time.Pad1 = 0; Time.Nanosecond = 0; Time.TimeZone = 0; Time.Daylight = 0; Time.Pad2 = 0; CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; DescriptorData->AuthInfo.CertType = efi_cert_type; /* we're expecting an EFI signature list, so don't free the input since * it might not be in a pool */ #if 0 if (Payload != NULL) { FreePool(Payload); } #endif *DataSize = DescriptorSize + PayloadSize; *Data = NewData; return EFI_SUCCESS; }
/** Create 4G PageTable in SMRAM. @param[in] Is32BitPageTable Whether the page table is 32-bit PAE @return PageTable Address **/ UINT32 Gen4GPageTable ( IN BOOLEAN Is32BitPageTable ) { VOID *PageTable; UINTN Index; UINT64 *Pte; UINTN PagesNeeded; UINTN Low2MBoundary; UINTN High2MBoundary; UINTN Pages; UINTN GuardPage; UINT64 *Pdpte; UINTN PageIndex; UINTN PageAddress; Low2MBoundary = 0; High2MBoundary = 0; PagesNeeded = 0; if (FeaturePcdGet (PcdCpuSmmStackGuard)) { // // Add one more page for known good stack, then find the lower 2MB aligned address. // Low2MBoundary = (mSmmStackArrayBase + EFI_PAGE_SIZE) & ~(SIZE_2MB-1); // // Add two more pages for known good stack and stack guard page, // then find the lower 2MB aligned address. // High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1); PagesNeeded = ((High2MBoundary - Low2MBoundary) / SIZE_2MB) + 1; } // // Allocate the page table // PageTable = AllocatePageTableMemory (5 + PagesNeeded); ASSERT (PageTable != NULL); PageTable = (VOID *)((UINTN)PageTable); Pte = (UINT64*)PageTable; // // Zero out all page table entries first // ZeroMem (Pte, EFI_PAGES_TO_SIZE (1)); // // Set Page Directory Pointers // for (Index = 0; Index < 4; Index++) { Pte[Index] = ((UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1)) | mAddressEncMask | (Is32BitPageTable ? IA32_PAE_PDPTE_ATTRIBUTE_BITS : PAGE_ATTRIBUTE_BITS); } Pte += EFI_PAGE_SIZE / sizeof (*Pte); // // Fill in Page Directory Entries // for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) { Pte[Index] = (Index << 21) | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS; } Pdpte = (UINT64*)PageTable; if (FeaturePcdGet (PcdCpuSmmStackGuard)) { Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5); GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE; for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) { Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1)); Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS; // // Fill in Page Table Entries // Pte = (UINT64*)Pages; PageAddress = PageIndex; for (Index = 0; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) { if (PageAddress == GuardPage) { // // Mark the guard page as non-present // Pte[Index] = PageAddress | mAddressEncMask; GuardPage += mSmmStackSize; if (GuardPage > mSmmStackArrayEnd) { GuardPage = 0; } } else { Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS; } PageAddress+= EFI_PAGE_SIZE; } Pages += EFI_PAGE_SIZE; } } if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) { Pte = (UINT64*)(UINTN)(Pdpte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1)); if ((Pte[0] & IA32_PG_PS) == 0) { // 4K-page entries are already mapped. Just hide the first one anyway. Pte = (UINT64*)(UINTN)(Pte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1)); Pte[0] &= ~(UINT64)IA32_PG_P; // Hide page 0 } else { // Create 4K-page entries Pages = (UINTN)AllocatePageTableMemory (1); ASSERT (Pages != 0); Pte[0] = (UINT64)(Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS); Pte = (UINT64*)Pages; PageAddress = 0; Pte[0] = PageAddress | mAddressEncMask; // Hide page 0 but present left for (Index = 1; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) { PageAddress += EFI_PAGE_SIZE; Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS; } } } return (UINT32)(UINTN)PageTable; }
EFI_STATUS fsw_efi_dnode_getinfo(IN FSW_FILE_DATA *File, IN EFI_GUID *InformationType, IN OUT UINTN *BufferSize, OUT VOID *Buffer) { EFI_STATUS Status; FSW_VOLUME_DATA *Volume = (FSW_VOLUME_DATA *)File->shand.dnode->vol->host_data; EFI_FILE_SYSTEM_INFO *FSInfo; UINTN RequiredSize; struct fsw_volume_stat vsb; if (CompareGuid(InformationType, &GUID_NAME(FileInfo))) { #if DEBUG_LEVEL Print(L"fsw_efi_dnode_getinfo: FILE_INFO\n"); #endif Status = fsw_efi_dnode_fill_FileInfo(Volume, File->shand.dnode, BufferSize, Buffer); } else if (CompareGuid(InformationType, &GUID_NAME(FileSystemInfo)) == 0) { #if DEBUG_LEVEL Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_INFO\n"); #endif // check buffer size RequiredSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + fsw_efi_strsize(&Volume->vol->label); if (*BufferSize < RequiredSize) { *BufferSize = RequiredSize; return EFI_BUFFER_TOO_SMALL; } // fill structure FSInfo = (EFI_FILE_SYSTEM_INFO *)Buffer; FSInfo->Size = RequiredSize; FSInfo->ReadOnly = TRUE; FSInfo->BlockSize = Volume->vol->log_blocksize; fsw_efi_strcpy(FSInfo->VolumeLabel, &Volume->vol->label); // get the missing info from the fs driver ZeroMem(&vsb, sizeof(struct fsw_volume_stat)); Status = fsw_efi_map_status(fsw_volume_stat(Volume->vol, &vsb), Volume); if (EFI_ERROR(Status)) return Status; FSInfo->VolumeSize = vsb.total_bytes; FSInfo->FreeSpace = vsb.free_bytes; // prepare for return *BufferSize = RequiredSize; Status = EFI_SUCCESS; } else if (CompareGuid(InformationType, &GUID_NAME(FileSystemVolumeLabelInfoId))) { #if DEBUG_LEVEL Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_VOLUME_LABEL\n"); #endif // check buffer size RequiredSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + fsw_efi_strsize(&Volume->vol->label); if (*BufferSize < RequiredSize) { *BufferSize = RequiredSize; return EFI_BUFFER_TOO_SMALL; } // copy volume label fsw_efi_strcpy(((EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Buffer)->VolumeLabel, &Volume->vol->label); // prepare for return *BufferSize = RequiredSize; Status = EFI_SUCCESS; } else { Status = EFI_UNSUPPORTED; } return Status; }
/** Get selection for OneOf and OrderedList (Left/Right will be ignored). @param MenuOption Pointer to the current input menu. @retval EFI_SUCCESS If Option input is processed successfully @retval EFI_DEVICE_ERROR If operation fails **/ EFI_STATUS GetSelectionInputPopUp ( IN UI_MENU_OPTION *MenuOption ) { EFI_INPUT_KEY Key; UINTN Index; CHAR16 *StringPtr; CHAR16 *TempStringPtr; UINTN Index2; UINTN TopOptionIndex; UINTN HighlightOptionIndex; UINTN Start; UINTN End; UINTN Top; UINTN Bottom; UINTN PopUpMenuLines; UINTN MenuLinesInView; UINTN PopUpWidth; CHAR16 Character; INT32 SavedAttribute; BOOLEAN ShowDownArrow; BOOLEAN ShowUpArrow; UINTN DimensionsWidth; LIST_ENTRY *Link; BOOLEAN OrderedList; UINT8 *ValueArray; UINT8 *ReturnValue; UINT8 ValueType; EFI_HII_VALUE HiiValue; DISPLAY_QUESTION_OPTION *OneOfOption; DISPLAY_QUESTION_OPTION *CurrentOption; FORM_DISPLAY_ENGINE_STATEMENT *Question; INTN Result; EFI_IFR_ORDERED_LIST *OrderList; DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn; ValueArray = NULL; ValueType = 0; CurrentOption = NULL; ShowDownArrow = FALSE; ShowUpArrow = FALSE; ZeroMem (&HiiValue, sizeof (EFI_HII_VALUE)); Question = MenuOption->ThisTag; if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) { Link = GetFirstNode (&Question->OptionListHead); OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); ValueArray = Question->CurrentValue.Buffer; ValueType = OneOfOption->OptionOpCode->Type; OrderedList = TRUE; OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode; } else { OrderedList = FALSE; OrderList = NULL; } // // Calculate Option count // PopUpMenuLines = 0; if (OrderedList) { AdjustOptionOrder(Question, &PopUpMenuLines); } else { Link = GetFirstNode (&Question->OptionListHead); while (!IsNull (&Question->OptionListHead, Link)) { OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); PopUpMenuLines++; Link = GetNextNode (&Question->OptionListHead, Link); } } // // Get the number of one of options present and its size // PopUpWidth = 0; HighlightOptionIndex = 0; Link = GetFirstNode (&Question->OptionListHead); for (Index = 0; Index < PopUpMenuLines; Index++) { OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle); if (StrLen (StringPtr) > PopUpWidth) { PopUpWidth = StrLen (StringPtr); } FreePool (StringPtr); HiiValue.Type = OneOfOption->OptionOpCode->Type; SetValuesByType (&HiiValue.Value, &OneOfOption->OptionOpCode->Value, HiiValue.Type); if (!OrderedList && (CompareHiiValue (&Question->CurrentValue, &HiiValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) { // // Find current selected Option for OneOf // HighlightOptionIndex = Index; } Link = GetNextNode (&Question->OptionListHead, Link); } // // Perform popup menu initialization. // PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT; SavedAttribute = gST->ConOut->Mode->Attribute; gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) { PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH; } Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gStatementDimensions.LeftColumn; End = Start + PopUpWidth + POPUP_FRAME_WIDTH; Top = gStatementDimensions.TopRow; Bottom = gStatementDimensions.BottomRow - 1; MenuLinesInView = Bottom - Top - 1; if (MenuLinesInView >= PopUpMenuLines) { Top = Top + (MenuLinesInView - PopUpMenuLines) / 2; Bottom = Top + PopUpMenuLines + 1; } else { ShowDownArrow = TRUE; } if (HighlightOptionIndex > (MenuLinesInView - 1)) { TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1; } else { TopOptionIndex = 0; } do { // // Clear that portion of the screen // ClearLines (Start, End, Top, Bottom, GetPopupColor ()); // // Draw "One of" pop-up menu // Character = BOXDRAW_DOWN_RIGHT; PrintCharAt (Start, Top, Character); for (Index = Start; Index + 2 < End; Index++) { if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) { Character = GEOMETRICSHAPE_UP_TRIANGLE; } else { Character = BOXDRAW_HORIZONTAL; } PrintCharAt ((UINTN)-1, (UINTN)-1, Character); } Character = BOXDRAW_DOWN_LEFT; PrintCharAt ((UINTN)-1, (UINTN)-1, Character); Character = BOXDRAW_VERTICAL; for (Index = Top + 1; Index < Bottom; Index++) { PrintCharAt (Start, Index, Character); PrintCharAt (End - 1, Index, Character); } // // Move to top Option // Link = GetFirstNode (&Question->OptionListHead); for (Index = 0; Index < TopOptionIndex; Index++) { Link = GetNextNode (&Question->OptionListHead, Link); } // // Display the One of options // Index2 = Top + 1; for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) { OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); Link = GetNextNode (&Question->OptionListHead, Link); StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle); ASSERT (StringPtr != NULL); // // If the string occupies multiple lines, truncate it to fit in one line, // and append a "..." for indication. // if (StrLen (StringPtr) > (PopUpWidth - 1)) { TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1)); ASSERT ( TempStringPtr != NULL ); CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5))); FreePool (StringPtr); StringPtr = TempStringPtr; StrCatS (StringPtr, PopUpWidth - 1, L"..."); } if (Index == HighlightOptionIndex) { // // Highlight the selected one // CurrentOption = OneOfOption; gST->ConOut->SetAttribute (gST->ConOut, GetPickListColor ()); PrintStringAt (Start + 2, Index2, StringPtr); gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); } else { gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); PrintStringAt (Start + 2, Index2, StringPtr); } Index2++; FreePool (StringPtr); } Character = BOXDRAW_UP_RIGHT; PrintCharAt (Start, Bottom, Character); for (Index = Start; Index + 2 < End; Index++) { if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) { Character = GEOMETRICSHAPE_DOWN_TRIANGLE; } else { Character = BOXDRAW_HORIZONTAL; } PrintCharAt ((UINTN)-1, (UINTN)-1, Character); } Character = BOXDRAW_UP_LEFT; PrintCharAt ((UINTN)-1, (UINTN)-1, Character); // // Get User selection // Key.UnicodeChar = CHAR_NULL; if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) { Key.ScanCode = gDirection; gDirection = 0; goto TheKey; } WaitForKeyStroke (&Key); TheKey: switch (Key.UnicodeChar) { case '+': if (OrderedList) { if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { // // Highlight reaches the top of the popup window, scroll one menu item. // TopOptionIndex--; ShowDownArrow = TRUE; } if (TopOptionIndex == 0) { ShowUpArrow = FALSE; } if (HighlightOptionIndex > 0) { HighlightOptionIndex--; ASSERT (CurrentOption != NULL); SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link); } } break; case '-': // // If an ordered list op-code, we will allow for a popup of +/- keys // to create an ordered list of items // if (OrderedList) { if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { // // Highlight reaches the bottom of the popup window, scroll one menu item. // TopOptionIndex++; ShowUpArrow = TRUE; } if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { ShowDownArrow = FALSE; } if (HighlightOptionIndex < (PopUpMenuLines - 1)) { HighlightOptionIndex++; ASSERT (CurrentOption != NULL); SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink); } } break; case CHAR_NULL: switch (Key.ScanCode) { case SCAN_UP: case SCAN_DOWN: if (Key.ScanCode == SCAN_UP) { if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) { // // Highlight reaches the top of the popup window, scroll one menu item. // TopOptionIndex--; ShowDownArrow = TRUE; } if (TopOptionIndex == 0) { ShowUpArrow = FALSE; } if (HighlightOptionIndex > 0) { HighlightOptionIndex--; } } else { if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) && (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) { // // Highlight reaches the bottom of the popup window, scroll one menu item. // TopOptionIndex++; ShowUpArrow = TRUE; } if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) { ShowDownArrow = FALSE; } if (HighlightOptionIndex < (PopUpMenuLines - 1)) { HighlightOptionIndex++; } } break; case SCAN_ESC: gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); // // Restore link list order for orderedlist // if (OrderedList) { HiiValue.Type = ValueType; HiiValue.Value.u64 = 0; for (Index = 0; Index < OrderList->MaxContainers; Index++) { HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index); if (HiiValue.Value.u64 == 0) { break; } OneOfOption = ValueToOption (Question, &HiiValue); if (OneOfOption == NULL) { return EFI_NOT_FOUND; } RemoveEntryList (&OneOfOption->Link); InsertTailList (&Question->OptionListHead, &OneOfOption->Link); } } return EFI_DEVICE_ERROR; default: break; } break; case CHAR_CARRIAGE_RETURN: // // return the current selection // if (OrderedList) { ReturnValue = AllocateZeroPool (Question->CurrentValue.BufferLen); ASSERT (ReturnValue != NULL); Index = 0; Link = GetFirstNode (&Question->OptionListHead); while (!IsNull (&Question->OptionListHead, Link)) { OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link); Link = GetNextNode (&Question->OptionListHead, Link); SetArrayData (ReturnValue, ValueType, Index, OneOfOption->OptionOpCode->Value.u64); Index++; if (Index > OrderList->MaxContainers) { break; } } if (CompareMem (ReturnValue, ValueArray, Question->CurrentValue.BufferLen) == 0) { FreePool (ReturnValue); return EFI_DEVICE_ERROR; } else { gUserInput->InputValue.Buffer = ReturnValue; gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen; } } else { ASSERT (CurrentOption != NULL); gUserInput->InputValue.Type = CurrentOption->OptionOpCode->Type; if (IsValuesEqual (&Question->CurrentValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type)) { return EFI_DEVICE_ERROR; } else { SetValuesByType (&gUserInput->InputValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type); } } gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); return EFI_SUCCESS; default: break; } } while (TRUE); }
EFI_STATUS EFIAPI SetPeiCacheMode ( IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; PEI_CACHE_PPI *CachePpi; EFI_BOOT_MODE BootMode; UINT64 MemoryLength; UINT64 MemOverflow; UINT64 MemoryLengthUc; UINT64 MaxMemoryLength; UINT64 LowMemoryLength; UINT64 HighMemoryLength; UINT8 Index; MTRR_SETTINGS MtrrSetting; UINT64 ValidMtrrAddressMask; // // Load Cache PPI // Status = (**PeiServices).LocatePpi ( PeiServices, &gPeiCachePpiGuid, // GUID 0, // Instance NULL, // EFI_PEI_PPI_DESCRIPTOR (void **)&CachePpi // PPI ); if (!EFI_ERROR(Status)) { // // Clear the CAR Settings (Default Cache Type => UC) // DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n")); CachePpi->ResetCache( (EFI_PEI_SERVICES**)PeiServices, CachePpi ); } // // Variable initialization // LowMemoryLength = 0; HighMemoryLength = 0; MemoryLengthUc = 0; Status = (*PeiServices)->GetBootMode ( PeiServices, &BootMode ); ValidMtrrAddressMask = InitializeAddressMtrrMask (); // // Determine memory usage // GetMemorySize ( PeiServices, &LowMemoryLength, &HighMemoryLength ); LowMemoryLength = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70); LowMemoryLength &= 0xFFF00000ULL; MaxMemoryLength = LowMemoryLength; // // Round up to nearest 256MB with high memory and 64MB w/o high memory // if (HighMemoryLength != 0 ) { MemOverflow = (LowMemoryLength & 0x0fffffff); if (MemOverflow != 0) { MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow); } } else { MemOverflow = (LowMemoryLength & 0x03ffffff); if (MemOverflow != 0) { MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow); } } ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS)); for (Index = 0; Index < 2; Index++) { MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606; } for (Index = 2; Index < 11; Index++) { MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505; } // // Cache the flash area to improve the boot performance in PEI phase // Index = 0; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Uint64 = FixedPcdGet32 (PcdFlashAreaBaseAddress); ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Bits.Type = CacheWriteProtected; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Uint64 = (~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Bits.V = 1; Index ++; MemOverflow =0; while (MaxMemoryLength > MemOverflow){ MemoryLength = MaxMemoryLength - MemOverflow; MemoryLength = GetPowerOfTwo64 (MemoryLength); ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1; MemOverflow += MemoryLength; Index++; } MemoryLength = LowMemoryLength; while (MaxMemoryLength != MemoryLength) { MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = (MaxMemoryLength - MemoryLengthUc) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheUncacheable; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLengthUc - 1)) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1; MaxMemoryLength -= MemoryLengthUc; Index++; } MemOverflow =0x100000000; while (HighMemoryLength > 0) { MemoryLength = HighMemoryLength; MemoryLength = GetPowerOfTwo64 (MemoryLength); if (MemoryLength > MemOverflow){ MemoryLength = MemOverflow; } ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask; ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1; MemOverflow += MemoryLength; HighMemoryLength -= MemoryLength; Index++; } for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) { if (MtrrSetting.Variables.Mtrr[Index].Base == 0){ break; } DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask)); } // // set FE/E bits for IA32_MTRR_DEF_TYPE // MtrrSetting.MtrrDefType |= 3 <<10; MtrrSetAllMtrrs(&MtrrSetting); // // Dump MTRR Setting // MtrrDebugPrintAllMtrrs (); return EFI_SUCCESS; }
/** This routine reads a numeric value from the user input. @param MenuOption Pointer to the current input menu. @retval EFI_SUCCESS If numerical input is read successfully @retval EFI_DEVICE_ERROR If operation fails **/ EFI_STATUS GetNumericInput ( IN UI_MENU_OPTION *MenuOption ) { UINTN Column; UINTN Row; CHAR16 InputText[MAX_NUMERIC_INPUT_WIDTH]; CHAR16 FormattedNumber[MAX_NUMERIC_INPUT_WIDTH - 1]; UINT64 PreviousNumber[MAX_NUMERIC_INPUT_WIDTH - 3]; UINTN Count; UINTN Loop; BOOLEAN ManualInput; BOOLEAN HexInput; BOOLEAN IntInput; BOOLEAN Negative; BOOLEAN ValidateFail; BOOLEAN DateOrTime; UINTN InputWidth; UINT64 EditValue; UINT64 Step; UINT64 Minimum; UINT64 Maximum; UINTN EraseLen; UINT8 Digital; EFI_INPUT_KEY Key; EFI_HII_VALUE *QuestionValue; FORM_DISPLAY_ENGINE_STATEMENT *Question; EFI_IFR_NUMERIC *NumericOp; UINT16 StorageWidth; Column = MenuOption->OptCol; Row = MenuOption->Row; PreviousNumber[0] = 0; Count = 0; InputWidth = 0; Digital = 0; StorageWidth = 0; Minimum = 0; Maximum = 0; NumericOp = NULL; IntInput = FALSE; HexInput = FALSE; Negative = FALSE; ValidateFail = FALSE; Question = MenuOption->ThisTag; QuestionValue = &Question->CurrentValue; ZeroMem (InputText, MAX_NUMERIC_INPUT_WIDTH * sizeof (CHAR16)); // // Only two case, user can enter to this function: Enter and +/- case. // In Enter case, gDirection = 0; in +/- case, gDirection = SCAN_LEFT/SCAN_WRIGHT // ManualInput = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE); if ((Question->OpCode->OpCode == EFI_IFR_DATE_OP) || (Question->OpCode->OpCode == EFI_IFR_TIME_OP)) { DateOrTime = TRUE; } else { DateOrTime = FALSE; } // // Prepare Value to be edit // EraseLen = 0; EditValue = 0; if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { Step = 1; Minimum = 1; switch (MenuOption->Sequence) { case 0: Maximum = 12; EraseLen = 4; EditValue = QuestionValue->Value.date.Month; break; case 1: switch (QuestionValue->Value.date.Month) { case 2: if ((QuestionValue->Value.date.Year % 4) == 0 && ((QuestionValue->Value.date.Year % 100) != 0 || (QuestionValue->Value.date.Year % 400) == 0)) { Maximum = 29; } else { Maximum = 28; } break; case 4: case 6: case 9: case 11: Maximum = 30; break; default: Maximum = 31; break; } EraseLen = 3; EditValue = QuestionValue->Value.date.Day; break; case 2: Maximum = 0xffff; EraseLen = 5; EditValue = QuestionValue->Value.date.Year; break; default: break; } } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { Step = 1; Minimum = 0; switch (MenuOption->Sequence) { case 0: Maximum = 23; EraseLen = 4; EditValue = QuestionValue->Value.time.Hour; break; case 1: Maximum = 59; EraseLen = 3; EditValue = QuestionValue->Value.time.Minute; break; case 2: Maximum = 59; EraseLen = 3; EditValue = QuestionValue->Value.time.Second; break; default: break; } } else { ASSERT (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP); NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode; GetValueFromNum(Question->OpCode, (NumericOp->Flags & EFI_IFR_DISPLAY) == 0, QuestionValue, &EditValue, &Minimum, &Maximum, &Step, &StorageWidth); EraseLen = gOptionBlockWidth; } if ((Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL)) { if ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX){ HexInput = TRUE; } else if ((NumericOp->Flags & EFI_IFR_DISPLAY) == 0){ // // Display with EFI_IFR_DISPLAY_INT_DEC type. Support negative number. // IntInput = TRUE; } } // // Enter from "Enter" input, clear the old word showing. // if (ManualInput) { if (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) { if (HexInput) { InputWidth = StorageWidth * 2; } else { switch (StorageWidth) { case 1: InputWidth = 3; break; case 2: InputWidth = 5; break; case 4: InputWidth = 10; break; case 8: InputWidth = 20; break; default: InputWidth = 0; break; } if (IntInput) { // // Support an extra '-' for negative number. // InputWidth += 1; } } InputText[0] = LEFT_NUMERIC_DELIMITER; SetUnicodeMem (InputText + 1, InputWidth, L' '); ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH); InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER; InputText[InputWidth + 2] = L'\0'; PrintStringAt (Column, Row, InputText); Column++; } if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { if (MenuOption->Sequence == 2) { InputWidth = 4; } else { InputWidth = 2; } if (MenuOption->Sequence == 0) { InputText[0] = LEFT_NUMERIC_DELIMITER; SetUnicodeMem (InputText + 1, InputWidth, L' '); InputText[InputWidth + 1] = DATE_SEPARATOR; InputText[InputWidth + 2] = L'\0'; } else if (MenuOption->Sequence == 1){ SetUnicodeMem (InputText, InputWidth, L' '); InputText[InputWidth] = DATE_SEPARATOR; InputText[InputWidth + 1] = L'\0'; } else { SetUnicodeMem (InputText, InputWidth, L' '); InputText[InputWidth] = RIGHT_NUMERIC_DELIMITER; InputText[InputWidth + 1] = L'\0'; } PrintStringAt (Column, Row, InputText); if (MenuOption->Sequence == 0) { Column++; } } if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { InputWidth = 2; if (MenuOption->Sequence == 0) { InputText[0] = LEFT_NUMERIC_DELIMITER; SetUnicodeMem (InputText + 1, InputWidth, L' '); InputText[InputWidth + 1] = TIME_SEPARATOR; InputText[InputWidth + 2] = L'\0'; } else if (MenuOption->Sequence == 1){ SetUnicodeMem (InputText, InputWidth, L' '); InputText[InputWidth] = TIME_SEPARATOR; InputText[InputWidth + 1] = L'\0'; } else { SetUnicodeMem (InputText, InputWidth, L' '); InputText[InputWidth] = RIGHT_NUMERIC_DELIMITER; InputText[InputWidth + 1] = L'\0'; } PrintStringAt (Column, Row, InputText); if (MenuOption->Sequence == 0) { Column++; } } } // // First time we enter this handler, we need to check to see if // we were passed an increment or decrement directive // do { Key.UnicodeChar = CHAR_NULL; if (gDirection != 0) { Key.ScanCode = gDirection; gDirection = 0; goto TheKey2; } WaitForKeyStroke (&Key); TheKey2: switch (Key.UnicodeChar) { case '+': case '-': if (ManualInput && IntInput) { // // In Manual input mode, check whether input the negative flag. // if (Key.UnicodeChar == '-') { if (Negative) { break; } Negative = TRUE; PrintCharAt (Column++, Row, Key.UnicodeChar); } } else { if (Key.UnicodeChar == '+') { Key.ScanCode = SCAN_RIGHT; } else { Key.ScanCode = SCAN_LEFT; } Key.UnicodeChar = CHAR_NULL; goto TheKey2; } break; case CHAR_NULL: switch (Key.ScanCode) { case SCAN_LEFT: case SCAN_RIGHT: if (DateOrTime && !ManualInput) { // // By setting this value, we will return back to the caller. // We need to do this since an auto-refresh will destroy the adjustment // based on what the real-time-clock is showing. So we always commit // upon changing the value. // gDirection = SCAN_DOWN; } if ((Step != 0) && !ManualInput) { if (Key.ScanCode == SCAN_LEFT) { if (IntInput) { if ((INT64) EditValue >= (INT64) Minimum + (INT64) Step) { EditValue = EditValue - Step; } else if ((INT64) EditValue > (INT64) Minimum){ EditValue = Minimum; } else { EditValue = Maximum; } } else { if (EditValue >= Minimum + Step) { EditValue = EditValue - Step; } else if (EditValue > Minimum){ EditValue = Minimum; } else { EditValue = Maximum; } } } else if (Key.ScanCode == SCAN_RIGHT) { if (IntInput) { if ((INT64) EditValue + (INT64) Step <= (INT64) Maximum) { EditValue = EditValue + Step; } else if ((INT64) EditValue < (INT64) Maximum) { EditValue = Maximum; } else { EditValue = Minimum; } } else { if (EditValue + Step <= Maximum) { EditValue = EditValue + Step; } else if (EditValue < Maximum) { EditValue = Maximum; } else { EditValue = Minimum; } } } ZeroMem (FormattedNumber, 21 * sizeof (CHAR16)); if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { if (MenuOption->Sequence == 2) { // // Year // UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", (UINT16) EditValue); } else { // // Month/Day // UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue); } if (MenuOption->Sequence == 0) { ASSERT (EraseLen >= 2); FormattedNumber[EraseLen - 2] = DATE_SEPARATOR; } else if (MenuOption->Sequence == 1) { ASSERT (EraseLen >= 1); FormattedNumber[EraseLen - 1] = DATE_SEPARATOR; } } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue); if (MenuOption->Sequence == 0) { ASSERT (EraseLen >= 2); FormattedNumber[EraseLen - 2] = TIME_SEPARATOR; } else if (MenuOption->Sequence == 1) { ASSERT (EraseLen >= 1); FormattedNumber[EraseLen - 1] = TIME_SEPARATOR; } } else { QuestionValue->Value.u64 = EditValue; PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16)); } gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ()); for (Loop = 0; Loop < EraseLen; Loop++) { PrintStringAt (MenuOption->OptCol + Loop, MenuOption->Row, L" "); } gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); if (MenuOption->Sequence == 0) { PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER); Column = MenuOption->OptCol + 1; } PrintStringAt (Column, Row, FormattedNumber); if (!DateOrTime || MenuOption->Sequence == 2) { PrintCharAt ((UINTN)-1, (UINTN)-1, RIGHT_NUMERIC_DELIMITER); } } goto EnterCarriageReturn; case SCAN_UP: case SCAN_DOWN: goto EnterCarriageReturn; case SCAN_ESC: return EFI_DEVICE_ERROR; default: break; } break; EnterCarriageReturn: case CHAR_CARRIAGE_RETURN: // // Validate input value with Minimum value. // ValidateFail = FALSE; if (IntInput) { // // After user input Enter, need to check whether the input value. // If input a negative value, should compare with maximum value. // else compare with the minimum value. // if (Negative) { ValidateFail = (INT64) EditValue > (INT64) Maximum ? TRUE : FALSE; } else { ValidateFail = (INT64) EditValue < (INT64) Minimum ? TRUE : FALSE; } if (ValidateFail) { UpdateStatusBar (INPUT_ERROR, TRUE); break; } } else if (EditValue < Minimum) { UpdateStatusBar (INPUT_ERROR, TRUE); break; } UpdateStatusBar (INPUT_ERROR, FALSE); CopyMem (&gUserInput->InputValue, &Question->CurrentValue, sizeof (EFI_HII_VALUE)); QuestionValue = &gUserInput->InputValue; // // Store Edit value back to Question // if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) { switch (MenuOption->Sequence) { case 0: QuestionValue->Value.date.Month = (UINT8) EditValue; break; case 1: QuestionValue->Value.date.Day = (UINT8) EditValue; break; case 2: QuestionValue->Value.date.Year = (UINT16) EditValue; break; default: break; } } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) { switch (MenuOption->Sequence) { case 0: QuestionValue->Value.time.Hour = (UINT8) EditValue; break; case 1: QuestionValue->Value.time.Minute = (UINT8) EditValue; break; case 2: QuestionValue->Value.time.Second = (UINT8) EditValue; break; default: break; } } else { // // Numeric // QuestionValue->Value.u64 = EditValue; } // // Adjust the value to the correct one. // Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01 // 2013.03.29 -> 2013.02.29 -> 2013.02.28 // if (Question->OpCode->OpCode == EFI_IFR_DATE_OP && (MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) { AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence); } return EFI_SUCCESS; case CHAR_BACKSPACE: if (ManualInput) { if (Count == 0) { if (Negative) { Negative = FALSE; Column--; PrintStringAt (Column, Row, L" "); } break; } // // Remove a character // EditValue = PreviousNumber[Count - 1]; UpdateStatusBar (INPUT_ERROR, FALSE); Count--; Column--; PrintStringAt (Column, Row, L" "); } break; default: if (ManualInput) { if (HexInput) { if ((Key.UnicodeChar >= L'0') && (Key.UnicodeChar <= L'9')) { Digital = (UINT8) (Key.UnicodeChar - L'0'); } else if ((Key.UnicodeChar >= L'A') && (Key.UnicodeChar <= L'F')) { Digital = (UINT8) (Key.UnicodeChar - L'A' + 0x0A); } else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) { Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A); } else { UpdateStatusBar (INPUT_ERROR, TRUE); break; } } else { if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') { UpdateStatusBar (INPUT_ERROR, TRUE); break; } } // // If Count exceed input width, there is no way more is valid // if (Count >= InputWidth) { break; } // // Someone typed something valid! // if (Count != 0) { if (HexInput) { EditValue = LShiftU64 (EditValue, 4) + Digital; } else if (IntInput && Negative) { // // Save the negative number. // EditValue = ~(MultU64x32 (~(EditValue - 1), 10) + (Key.UnicodeChar - L'0')) + 1; } else { EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0'); } } else { if (HexInput) { EditValue = Digital; } else if (IntInput && Negative) { // // Save the negative number. // EditValue = ~(Key.UnicodeChar - L'0') + 1; } else { EditValue = Key.UnicodeChar - L'0'; } } if (IntInput) { ValidateFail = FALSE; // // When user input a new value, should check the current value. // If user input a negative value, should compare it with minimum // value, else compare it with maximum value. // if (Negative) { ValidateFail = (INT64) EditValue < (INT64) Minimum ? TRUE : FALSE; } else { ValidateFail = (INT64) EditValue > (INT64) Maximum ? TRUE : FALSE; } if (ValidateFail) { UpdateStatusBar (INPUT_ERROR, TRUE); ASSERT (Count < ARRAY_SIZE (PreviousNumber)); EditValue = PreviousNumber[Count]; break; } } else { if (EditValue > Maximum) { UpdateStatusBar (INPUT_ERROR, TRUE); ASSERT (Count < ARRAY_SIZE (PreviousNumber)); EditValue = PreviousNumber[Count]; break; } } UpdateStatusBar (INPUT_ERROR, FALSE); Count++; ASSERT (Count < (ARRAY_SIZE (PreviousNumber))); PreviousNumber[Count] = EditValue; gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ()); PrintCharAt (Column, Row, Key.UnicodeChar); Column++; } break; } } while (TRUE); }
/** Fetch the Ifr binary data of a FormSet. @param Handle PackageList Handle @param FormSetGuid GUID of a formset. If not specified (NULL or zero GUID), take the first FormSet found in package list. @param BinaryLength The length of the FormSet IFR binary. @param BinaryData The buffer designed to receive the FormSet. @retval EFI_SUCCESS Buffer filled with the requested FormSet. BufferLength was updated. @retval EFI_INVALID_PARAMETER The handle is unknown. @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot be found with the requested FormId. **/ EFI_STATUS GetIfrBinaryData ( IN EFI_HII_HANDLE Handle, IN OUT EFI_GUID *FormSetGuid, OUT UINTN *BinaryLength, OUT UINT8 **BinaryData ) { EFI_STATUS Status; EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; UINTN BufferSize; UINT8 *Package; UINT8 *OpCodeData; UINT32 Offset; UINT32 Offset2; BOOLEAN ReturnDefault; UINT32 PackageListLength; EFI_HII_PACKAGE_HEADER PackageHeader; OpCodeData = NULL; Package = NULL; ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));; // // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list // if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) { ReturnDefault = TRUE; } else { ReturnDefault = FALSE; } // // Get HII PackageList // BufferSize = 0; HiiPackageList = NULL; Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); if (Status == EFI_BUFFER_TOO_SMALL) { HiiPackageList = AllocatePool (BufferSize); ASSERT (HiiPackageList != NULL); Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList); } if (EFI_ERROR (Status) || HiiPackageList == NULL) { return EFI_NOT_FOUND; } // // Get Form package from this HII package List // Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); Offset2 = 0; CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); while (Offset < PackageListLength) { 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 // Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); while (Offset2 < PackageHeader.Length) { OpCodeData = Package + Offset2; if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { // // Check whether return default FormSet // if (ReturnDefault) { break; } // // FormSet GUID is specified, check it // if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) { break; } } Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; } if (Offset2 < PackageHeader.Length) { // // Target formset found // break; } } Offset += PackageHeader.Length; } if (Offset >= PackageListLength) { // // Form package not found in this Package List // gBS->FreePool (HiiPackageList); return EFI_NOT_FOUND; } if (ReturnDefault && FormSetGuid != NULL) { // // Return the default FormSet GUID // CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)); } // // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes // in this FormSet; So, here just simply copy the data from start of a FormSet to the end // of the Form Package. // *BinaryLength = PackageHeader.Length - Offset2; *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData); gBS->FreePool (HiiPackageList); if (*BinaryData == NULL) { return EFI_OUT_OF_RESOURCES; } return EFI_SUCCESS; }
/** Function is used for allocating a bi-directional FW_CFG_DMA_ACCESS used between Host and device to exchange the information. The buffer must be free'd using FreeFwCfgDmaAccessBuffer (). **/ STATIC VOID AllocFwCfgDmaAccessBuffer ( OUT VOID **Access, OUT VOID **MapInfo ) { UINTN Size; UINTN NumPages; EFI_STATUS Status; VOID *HostAddress; EFI_PHYSICAL_ADDRESS DmaAddress; VOID *Mapping; Size = sizeof (FW_CFG_DMA_ACCESS); NumPages = EFI_SIZE_TO_PAGES (Size); // // As per UEFI spec, in order to map a host address with // BusMasterCommomBuffer64, the buffer must be allocated using the IOMMU // AllocateBuffer() // Status = mIoMmuProtocol->AllocateBuffer ( mIoMmuProtocol, AllocateAnyPages, EfiBootServicesData, NumPages, &HostAddress, EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a:%a failed to allocate FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName, __FUNCTION__)); ASSERT (FALSE); CpuDeadLoop (); } // // Avoid exposing stale data even temporarily: zero the area before mapping // it. // ZeroMem (HostAddress, Size); // // Map the host buffer with BusMasterCommonBuffer64 // Status = mIoMmuProtocol->Map ( mIoMmuProtocol, EdkiiIoMmuOperationBusMasterCommonBuffer64, HostAddress, &Size, &DmaAddress, &Mapping ); if (EFI_ERROR (Status)) { mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress); DEBUG ((DEBUG_ERROR, "%a:%a failed to Map() FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName, __FUNCTION__)); ASSERT (FALSE); CpuDeadLoop (); } if (Size < sizeof (FW_CFG_DMA_ACCESS)) { mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping); mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress); DEBUG ((DEBUG_ERROR, "%a:%a failed to Map() - requested 0x%Lx got 0x%Lx\n", gEfiCallerBaseName, __FUNCTION__, (UINT64)sizeof (FW_CFG_DMA_ACCESS), (UINT64)Size)); ASSERT (FALSE); CpuDeadLoop (); } *Access = HostAddress; *MapInfo = Mapping; }
/** Update the banner information for the Front Page based on DataHub information. **/ VOID UpdateFrontPageStrings ( VOID ) { UINT8 StrIndex; CHAR16 *NewString; BOOLEAN Find[5]; EFI_STATUS Status; EFI_STRING_ID TokenToUpdate; EFI_SMBIOS_HANDLE SmbiosHandle; EFI_SMBIOS_PROTOCOL *Smbios; SMBIOS_TABLE_TYPE0 *Type0Record; SMBIOS_TABLE_TYPE1 *Type1Record; SMBIOS_TABLE_TYPE4 *Type4Record; SMBIOS_TABLE_TYPE19 *Type19Record; EFI_SMBIOS_TABLE_HEADER *Record; ZeroMem (Find, sizeof (Find)); // // Update Front Page strings // Status = gBS->LocateProtocol ( &gEfiSmbiosProtocolGuid, NULL, (VOID **) &Smbios ); ASSERT_EFI_ERROR (Status); SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; do { Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL); if (EFI_ERROR(Status)) { break; } if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) { Type0Record = (SMBIOS_TABLE_TYPE0 *) Record; StrIndex = Type0Record->BiosVersion; GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString); TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION); HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); FreePool (NewString); Find[0] = TRUE; } if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) { Type1Record = (SMBIOS_TABLE_TYPE1 *) Record; StrIndex = Type1Record->ProductName; GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString); TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL); HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); FreePool (NewString); Find[1] = TRUE; } if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) { Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; StrIndex = Type4Record->ProcessorVersion; GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString); TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL); HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); FreePool (NewString); Find[2] = TRUE; } if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) { Type4Record = (SMBIOS_TABLE_TYPE4 *) Record; ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString); TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED); HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); FreePool (NewString); Find[3] = TRUE; } if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) { Type19Record = (SMBIOS_TABLE_TYPE19 *) Record; ConvertMemorySizeToString ( (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)), &NewString ); TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE); HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL); FreePool (NewString); Find[4] = TRUE; } } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4])); return ; }
/** Install child handles if the Handle supports Apple partition table format. @param[in] This Calling context. @param[in] Handle Parent Handle @param[in] DiskIo Parent DiskIo interface @param[in] BlockIo Parent BlockIo interface @param[in] DevicePath Parent Device Path @retval EFI_SUCCESS Child handle(s) was added @retval EFI_MEDIA_CHANGED Media changed Detected @retval other no child handle was added **/ EFI_STATUS PartitionInstallAppleChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; EFI_BLOCK_IO_MEDIA *Media; CDROM_DEVICE_PATH CdDev; UINT32 Partition; UINT32 PartitionEntries; UINT32 VolSpaceSize; UINT32 SubBlockSize; UINT32 BlkPerSec; UINT32 MediaId; UINT32 BlockSize; EFI_LBA LastBlock; APPLE_PT_HEADER *AppleHeader; APPLE_PT_ENTRY *AppleEntry; UINT32 StartLba; UINT32 SizeLbs; AppleEntry = NULL; Media = BlockIo->Media; BlockSize = BlockIo->Media->BlockSize; LastBlock = BlockIo->Media->LastBlock; MediaId = BlockIo->Media->MediaId; VolSpaceSize = 0; AppleHeader = AllocatePool (BlockSize); if (AppleHeader == NULL) { return EFI_NOT_FOUND; } do { Status = DiskIo->ReadDisk ( DiskIo, MediaId, 0, BlockSize, AppleHeader ); if (EFI_ERROR (Status)) { goto done; } if (SwapBytes16(AppleHeader->sbSig) != 0x4552) { Status = EFI_NOT_FOUND; goto done; } SubBlockSize = SwapBytes16(AppleHeader->sbBlkSize); BlkPerSec = BlockSize / SubBlockSize; if (BlockSize != SubBlockSize * BlkPerSec) { Status = EFI_NOT_FOUND; goto done; } AppleEntry = AllocatePool (SubBlockSize); PartitionEntries = 1; for (Partition = 1; Partition <= PartitionEntries; Partition++) { Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32 (Partition, SubBlockSize), SubBlockSize, AppleEntry ); if (EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; goto done; /* would break, but ... */ } if (SwapBytes16(AppleEntry->signature) != 0x504D) { continue; } if (Partition == 1) { PartitionEntries = SwapBytes32(AppleEntry->map_entries); } StartLba = SwapBytes32(AppleEntry->pblock_start); SizeLbs = SwapBytes32(AppleEntry->pblocks); ZeroMem (&CdDev, sizeof (CdDev)); CdDev.Header.Type = MEDIA_DEVICE_PATH; CdDev.Header.SubType = MEDIA_CDROM_DP; SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev)); CdDev.BootEntry = 0; CdDev.PartitionStart = StartLba / BlkPerSec; /* start, LBA */ CdDev.PartitionSize = SizeLbs / BlkPerSec; /* size, LBs */ Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &CdDev, CdDev.PartitionStart, CdDev.PartitionStart + CdDev.PartitionSize - 1, SubBlockSize, FALSE ); } } while (0); done: if (AppleHeader != NULL) { FreePool (AppleHeader); } if (AppleEntry != NULL) { FreePool (AppleEntry); } return Status; }
/** Create a new TCP4 or TCP6 driver service binding protocol @param[in] Controller Controller handle of device to bind driver to. @param[in] Image The TCP driver's image handle. @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources. @retval EFI_SUCCESS A new IP6 service binding private was created. **/ EFI_STATUS TcpCreateService ( IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN UINT8 IpVersion ) { EFI_STATUS Status; EFI_GUID *IpServiceBindingGuid; EFI_GUID *TcpServiceBindingGuid; TCP_SERVICE_DATA *TcpServiceData; IP_IO_OPEN_DATA OpenData; if (IpVersion == IP_VERSION_4) { IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid; TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid; } else { IpServiceBindingGuid = &gEfiIp6ServiceBindingProtocolGuid; TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid; } Status = gBS->OpenProtocol ( Controller, TcpServiceBindingGuid, NULL, Image, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (!EFI_ERROR (Status)) { return EFI_ALREADY_STARTED; } Status = gBS->OpenProtocol ( Controller, IpServiceBindingGuid, NULL, Image, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } // // Create the TCP service data. // TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA)); if (TcpServiceData == NULL) { return EFI_OUT_OF_RESOURCES; } TcpServiceData->Signature = TCP_DRIVER_SIGNATURE; TcpServiceData->ControllerHandle = Controller; TcpServiceData->DriverBindingHandle = Image; TcpServiceData->IpVersion = IpVersion; CopyMem ( &TcpServiceData->ServiceBinding, &gTcpServiceBinding, sizeof (EFI_SERVICE_BINDING_PROTOCOL) ); TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion); if (TcpServiceData->IpIo == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_ERROR; } InitializeListHead (&TcpServiceData->SocketList); ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA)); if (IpVersion == IP_VERSION_4) { CopyMem ( &OpenData.IpConfigData.Ip4CfgData, &mIp4IoDefaultIpConfigData, sizeof (EFI_IP4_CONFIG_DATA) ); OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP; } else { CopyMem ( &OpenData.IpConfigData.Ip6CfgData, &mIp6IoDefaultIpConfigData, sizeof (EFI_IP6_CONFIG_DATA) ); OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP; } OpenData.PktRcvdNotify = TcpRxCallback; Status = IpIoOpen (TcpServiceData->IpIo, &OpenData); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = TcpCreateTimer (); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, TcpServiceBindingGuid, &TcpServiceData->ServiceBinding, NULL ); if (EFI_ERROR (Status)) { TcpDestroyTimer (); goto ON_ERROR; } return EFI_SUCCESS; ON_ERROR: if (TcpServiceData->IpIo != NULL) { IpIoDestroy (TcpServiceData->IpIo); TcpServiceData->IpIo = NULL; } FreePool (TcpServiceData); return Status; }
/** Create popup window. It will replace CreateDialog(). This function draws OEM/Vendor specific pop up windows. @param[out] Key User Input Key @param ... String to be shown in Popup. The variable argument list is terminated by a NULL. **/ VOID EFIAPI CreateDialog ( OUT EFI_INPUT_KEY *Key, OPTIONAL ... ) { VA_LIST Marker; EFI_INPUT_KEY KeyValue; EFI_STATUS Status; UINTN LargestString; UINTN LineNum; UINTN Index; UINTN Count; CHAR16 Character; UINTN Start; UINTN End; UINTN Top; UINTN Bottom; CHAR16 *String; UINTN DimensionsWidth; UINTN DimensionsHeight; UINTN CurrentAttribute; BOOLEAN CursorVisible; // // If screen dimension info is not ready, get it from console. // if (gScreenDimensions.RightColumn == 0 || gScreenDimensions.BottomRow == 0) { ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); gST->ConOut->QueryMode ( gST->ConOut, gST->ConOut->Mode->Mode, &gScreenDimensions.RightColumn, &gScreenDimensions.BottomRow ); } DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; LargestString = 0; LineNum = 0; VA_START (Marker, Key); while ((String = VA_ARG (Marker, CHAR16 *)) != NULL) { LineNum ++; if ((LibGetStringWidth (String) / 2) > LargestString) { LargestString = (LibGetStringWidth (String) / 2); } } VA_END (Marker); if ((LargestString + 2) > DimensionsWidth) { LargestString = DimensionsWidth - 2; } CurrentAttribute = gST->ConOut->Mode->Attribute; CursorVisible = gST->ConOut->Mode->CursorVisible; gST->ConOut->EnableCursor (gST->ConOut, FALSE); gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); // // Subtract the PopUp width from total Columns, allow for one space extra on // each end plus a border. // Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1; End = Start + LargestString + 1; Top = ((DimensionsHeight - LineNum - 2) / 2) + gScreenDimensions.TopRow - 1; Bottom = Top + LineNum + 2; Character = BOXDRAW_DOWN_RIGHT; PrintCharAt (Start, Top, Character); Character = BOXDRAW_HORIZONTAL; for (Index = Start; Index + 2 < End; Index++) { PrintCharAt ((UINTN)-1, (UINTN)-1, Character); } Character = BOXDRAW_DOWN_LEFT; PrintCharAt ((UINTN)-1, (UINTN)-1, Character); Character = BOXDRAW_VERTICAL; Count = 0; VA_START (Marker, Key); for (Index = Top; Index + 2 < Bottom; Index++, Count++) { String = VA_ARG (Marker, CHAR16*); if (String[0] == CHAR_NULL) { // // Passing in a NULL results in a blank space // ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); } else if (String[0] == L' ') { // // Passing in a space results in the assumption that this is where typing will occur // ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND); PrintStringAt ( ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1, Index + 1, String + 1 ); } else { // // This will clear the background of the line - we never know who might have been // here before us. This differs from the next clear in that it used the non-reverse // video for normal printing. // ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ()); PrintStringAt ( ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1, Index + 1, String ); } gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ()); PrintCharAt (Start, Index + 1, Character); PrintCharAt (End - 1, Index + 1, Character); } VA_END (Marker); Character = BOXDRAW_UP_RIGHT; PrintCharAt (Start, Bottom - 1, Character); Character = BOXDRAW_HORIZONTAL; for (Index = Start; Index + 2 < End; Index++) { PrintCharAt ((UINTN)-1, (UINTN) -1, Character); } Character = BOXDRAW_UP_LEFT; PrintCharAt ((UINTN)-1, (UINTN) -1, Character); if (Key != NULL) { Status = WaitForKeyStroke (&KeyValue); ASSERT_EFI_ERROR (Status); CopyMem (Key, &KeyValue, sizeof (EFI_INPUT_KEY)); } gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); }
/** Create PRP lists for data transfer which is larger than 2 memory pages. Note here we calcuate the number of required PRP lists and allocate them at one time. @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance. @param[in] PhysicalAddr The physical base address of data buffer. @param[in] Pages The number of pages to be transfered. @param[out] PrpListHost The host base address of PRP lists. @param[in,out] PrpListNo The number of PRP List. @param[out] Mapping The mapping value returned from PciIo.Map(). @retval The pointer to the first PRP List of the PRP lists. **/ VOID* NvmeCreatePrpList ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_PHYSICAL_ADDRESS PhysicalAddr, IN UINTN Pages, OUT VOID **PrpListHost, IN OUT UINTN *PrpListNo, OUT VOID **Mapping ) { UINTN PrpEntryNo; UINT64 PrpListBase; UINTN PrpListIndex; UINTN PrpEntryIndex; UINT64 Remainder; EFI_PHYSICAL_ADDRESS PrpListPhyAddr; UINTN Bytes; EFI_STATUS Status; // // The number of Prp Entry in a memory page. // PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64); // // Calculate total PrpList number. // *PrpListNo = (UINTN)DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo - 1, &Remainder); if (*PrpListNo == 0) { *PrpListNo = 1; } else if ((Remainder != 0) && (Remainder != 1)) { *PrpListNo += 1; } else if (Remainder == 1) { Remainder = PrpEntryNo; } else if (Remainder == 0) { Remainder = PrpEntryNo - 1; } Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, *PrpListNo, PrpListHost, 0 ); if (EFI_ERROR (Status)) { return NULL; } Bytes = EFI_PAGES_TO_SIZE (*PrpListNo); Status = PciIo->Map ( PciIo, EfiPciIoOperationBusMasterCommonBuffer, *PrpListHost, &Bytes, &PrpListPhyAddr, Mapping ); if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (*PrpListNo))) { DEBUG ((EFI_D_ERROR, "NvmeCreatePrpList: create PrpList failure!\n")); goto EXIT; } // // Fill all PRP lists except of last one. // ZeroMem (*PrpListHost, Bytes); for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) { PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) { if (PrpEntryIndex != PrpEntryNo - 1) { // // Fill all PRP entries except of last one. // *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr; PhysicalAddr += EFI_PAGE_SIZE; } else { // // Fill last PRP entries with next PRP List pointer. // *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE; } } } // // Fill last PRP list. // PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < Remainder; ++PrpEntryIndex) { *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr; PhysicalAddr += EFI_PAGE_SIZE; } return (VOID*)(UINTN)PrpListPhyAddr; EXIT: PciIo->FreeBuffer (PciIo, *PrpListNo, *PrpListHost); return NULL; }
/** Function to handle the MTFTP OACK packet. It parses the packet's options, and update the internal states of the session. @param Instance The MTFTP session @param Packet The received OACK packet @param Len The length of the packet @param Completed Whether the transmisson has completed. NOT used by this function. @retval EFI_SUCCESS The OACK process is OK @retval EFI_TFTP_ERROR Some error occured, and the session reset. **/ EFI_STATUS Mtftp4WrqHandleOack ( IN OUT MTFTP4_PROTOCOL *Instance, IN EFI_MTFTP4_PACKET *Packet, IN UINT32 Len, OUT BOOLEAN *Completed ) { MTFTP4_OPTION Reply; EFI_MTFTP4_PACKET Bogus; EFI_STATUS Status; INTN Expected; *Completed = FALSE; // // Ignore the OACK if already started the upload // Expected = Mtftp4GetNextBlockNum (&Instance->Blocks); if (Expected != 0) { return EFI_SUCCESS; } // // Parse and validate the options from server // ZeroMem (&Reply, sizeof (MTFTP4_OPTION)); Status = Mtftp4ParseOptionOack (Packet, Len, &Reply); if (EFI_ERROR (Status) || !Mtftp4WrqOackValid (&Reply, &Instance->RequestOption)) { // // Don't send a MTFTP error packet when out of resource, it can // only make it worse. // if (Status != EFI_OUT_OF_RESOURCES) { Mtftp4SendError ( Instance, EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION, (UINT8 *) "Mal-formated OACK packet" ); } return EFI_TFTP_ERROR; } if (Reply.BlkSize != 0) { Instance->BlkSize = Reply.BlkSize; } if (Reply.Timeout != 0) { Instance->Timeout = Reply.Timeout; } // // Build a bogus ACK0 packet then pass it to the Mtftp4WrqHandleAck, // which will start the transmission of the first data block. // Bogus.Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK); Bogus.Ack.Block[0] = 0; Status = Mtftp4WrqHandleAck ( Instance, &Bogus, sizeof (EFI_MTFTP4_ACK_HEADER), Completed ); return Status; }
/** Create PageTable for SMM use. @return The address of PML4 (to set CR3). **/ UINT32 SmmInitPageTable ( VOID ) { EFI_PHYSICAL_ADDRESS Pages; UINT64 *PTEntry; LIST_ENTRY *FreePage; UINTN Index; UINTN PageFaultHandlerHookAddress; IA32_IDT_GATE_DESCRIPTOR *IdtEntry; // // Initialize spin lock // InitializeSpinLock (&mPFLock); m1GPageTableSupport = Is1GPageSupport (); // // Generate PAE page table for the first 4GB memory space // Pages = Gen4GPageTable (PAGE_TABLE_PAGES + 1); // // Set IA32_PG_PMNT bit to mask this entry // PTEntry = (UINT64*)(UINTN)Pages; for (Index = 0; Index < 4; Index++) { PTEntry[Index] |= IA32_PG_PMNT; } // // Fill Page-Table-Level4 (PML4) entry // PTEntry = (UINT64*)(UINTN)(Pages - EFI_PAGES_TO_SIZE (PAGE_TABLE_PAGES + 1)); *PTEntry = Pages + PAGE_ATTRIBUTE_BITS; ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry)); // // Set sub-entries number // SetSubEntriesNum (PTEntry, 3); // // Add remaining pages to page pool // FreePage = (LIST_ENTRY*)(PTEntry + EFI_PAGE_SIZE / sizeof (*PTEntry)); while ((UINTN)FreePage < Pages) { InsertTailList (&mPagePool, FreePage); FreePage += EFI_PAGE_SIZE / sizeof (*FreePage); } if (FeaturePcdGet (PcdCpuSmmProfileEnable)) { // // Set own Page Fault entry instead of the default one, because SMM Profile // feature depends on IRET instruction to do Single Step // PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile; IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base; IdtEntry += EXCEPT_IA32_PAGE_FAULT; IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress; IdtEntry->Bits.Reserved_0 = 0; IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32; IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16); IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32); IdtEntry->Bits.Reserved_1 = 0; } else {
/** Retrieve the host address using the EFI_DNS6_PROTOCOL. @param[in] Private The pointer to the driver's private data. @param[in] HostName Pointer to buffer containing hostname. @param[out] IpAddress On output, pointer to buffer containing IPv6 address. @retval EFI_SUCCESS Operation succeeded. @retval EFI_DEVICE_ERROR An unexpected network error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS HttpBootDns ( IN HTTP_BOOT_PRIVATE_DATA *Private, IN CHAR16 *HostName, OUT EFI_IPv6_ADDRESS *IpAddress ) { EFI_STATUS Status; EFI_DNS6_PROTOCOL *Dns6; EFI_DNS6_CONFIG_DATA Dns6ConfigData; EFI_DNS6_COMPLETION_TOKEN Token; EFI_HANDLE Dns6Handle; EFI_IP6_CONFIG_PROTOCOL *Ip6Config; EFI_IPv6_ADDRESS *DnsServerList; UINTN DnsServerListCount; UINTN DataSize; BOOLEAN IsDone; DnsServerList = NULL; DnsServerListCount = 0; Dns6 = NULL; Dns6Handle = NULL; ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN)); // // Get DNS server list from EFI IPv6 Configuration protocol. // Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config); if (!EFI_ERROR (Status)) { // // Get the required size. // DataSize = 0; Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { DnsServerList = AllocatePool (DataSize); if (DnsServerList == NULL) { return EFI_OUT_OF_RESOURCES; } Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList); if (EFI_ERROR (Status)) { FreePool (DnsServerList); DnsServerList = NULL; } else { DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS); } } } // // Create a DNSv6 child instance and get the protocol. // Status = NetLibCreateServiceChild ( Private->Controller, Private->Image, &gEfiDns6ServiceBindingProtocolGuid, &Dns6Handle ); if (EFI_ERROR (Status)) { goto Exit; } Status = gBS->OpenProtocol ( Dns6Handle, &gEfiDns6ProtocolGuid, (VOID **) &Dns6, Private->Image, Private->Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Exit; } // // Configure DNS6 instance for the DNS server address and protocol. // ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA)); Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount; Dns6ConfigData.DnsServerList = DnsServerList; Dns6ConfigData.EnableDnsCache = TRUE; Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP; IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6); Status = Dns6->Configure ( Dns6, &Dns6ConfigData ); if (EFI_ERROR (Status)) { goto Exit; } Token.Status = EFI_NOT_READY; IsDone = FALSE; // // Create event to set the IsDone flag when name resolution is finished. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, HttpBootCommonNotify, &IsDone, &Token.Event ); if (EFI_ERROR (Status)) { goto Exit; } // // Start asynchronous name resolution. // Status = Dns6->HostNameToIp (Dns6, HostName, &Token); if (EFI_ERROR (Status)) { goto Exit; } while (!IsDone) { Dns6->Poll (Dns6); } // // Name resolution is done, check result. // Status = Token.Status; if (!EFI_ERROR (Status)) { if (Token.RspData.H2AData == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } // // We just return the first IPv6 address from DNS protocol. // IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList); Status = EFI_SUCCESS; } Exit: if (Token.Event != NULL) { gBS->CloseEvent (Token.Event); } if (Token.RspData.H2AData != NULL) { if (Token.RspData.H2AData->IpList != NULL) { FreePool (Token.RspData.H2AData->IpList); } FreePool (Token.RspData.H2AData); } if (Dns6 != NULL) { Dns6->Configure (Dns6, NULL); gBS->CloseProtocol ( Dns6Handle, &gEfiDns6ProtocolGuid, Private->Image, Private->Controller ); } if (Dns6Handle != NULL) { NetLibDestroyServiceChild ( Private->Controller, Private->Image, &gEfiDns6ServiceBindingProtocolGuid, Dns6Handle ); } if (DnsServerList != NULL) { FreePool (DnsServerList); } return Status; }