/** The work function of EfiHttpResponse(). @param[in] Wrap Pointer to HTTP token's wrap data. @retval EFI_SUCCESS Allocation succeeded. @retval EFI_OUT_OF_RESOURCES Failed to complete the opration due to lack of resources. @retval EFI_NOT_READY Can't find a corresponding Tx4Token/Tx6Token or the EFI_HTTP_UTILITIES_PROTOCOL is not available. **/ EFI_STATUS HttpResponseWorker ( IN HTTP_TOKEN_WRAP *Wrap ) { EFI_STATUS Status; EFI_HTTP_MESSAGE *HttpMsg; CHAR8 *EndofHeader; CHAR8 *HttpHeaders; UINTN SizeofHeaders; UINTN BufferSize; UINTN StatusCode; CHAR8 *Tmp; CHAR8 *HeaderTmp; CHAR8 *StatusCodeStr; UINTN BodyLen; HTTP_PROTOCOL *HttpInstance; EFI_HTTP_TOKEN *Token; NET_MAP_ITEM *Item; HTTP_TOKEN_WRAP *ValueInItem; UINTN HdrLen; if (Wrap == NULL || Wrap->HttpInstance == NULL) { return EFI_INVALID_PARAMETER; } HttpInstance = Wrap->HttpInstance; Token = Wrap->HttpToken; HttpMsg = Token->Message; HttpInstance->EndofHeader = NULL; HttpInstance->HttpHeaders = NULL; HttpMsg->Headers = NULL; HttpHeaders = NULL; SizeofHeaders = 0; BufferSize = 0; EndofHeader = NULL; if (HttpMsg->Data.Response != NULL) { // // Need receive the HTTP headers, prepare buffer. // Status = HttpCreateTcpRxEventForHeader (HttpInstance); if (EFI_ERROR (Status)) { goto Error; } // // Check whether we have cached header from previous call. // if ((HttpInstance->CacheBody != NULL) && (HttpInstance->NextMsg != NULL)) { // // The data is stored at [NextMsg, CacheBody + CacheLen]. // HdrLen = HttpInstance->CacheBody + HttpInstance->CacheLen - HttpInstance->NextMsg; HttpHeaders = AllocateZeroPool (HdrLen); if (HttpHeaders == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } CopyMem (HttpHeaders, HttpInstance->NextMsg, HdrLen); FreePool (HttpInstance->CacheBody); HttpInstance->CacheBody = NULL; HttpInstance->NextMsg = NULL; HttpInstance->CacheOffset = 0; SizeofHeaders = HdrLen; BufferSize = HttpInstance->CacheLen; // // Check whether we cached the whole HTTP headers. // EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); } HttpInstance->EndofHeader = &EndofHeader; HttpInstance->HttpHeaders = &HttpHeaders; if (HttpInstance->TimeoutEvent == NULL) { // // Create TimeoutEvent for response // Status = gBS->CreateEvent ( EVT_TIMER, TPL_CALLBACK, NULL, NULL, &HttpInstance->TimeoutEvent ); if (EFI_ERROR (Status)) { goto Error; } } // // Start the timer, and wait Timeout seconds to receive the header packet. // Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_RESPONSE_TIMEOUT * TICKS_PER_SECOND); if (EFI_ERROR (Status)) { goto Error; } Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize, HttpInstance->TimeoutEvent); gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0); if (EFI_ERROR (Status)) { goto Error; } ASSERT (HttpHeaders != NULL); // // Cache the part of body. // BodyLen = BufferSize - (EndofHeader - HttpHeaders); if (BodyLen > 0) { if (HttpInstance->CacheBody != NULL) { FreePool (HttpInstance->CacheBody); } HttpInstance->CacheBody = AllocateZeroPool (BodyLen); if (HttpInstance->CacheBody == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } CopyMem (HttpInstance->CacheBody, EndofHeader, BodyLen); HttpInstance->CacheLen = BodyLen; } // // Search for Status Code. // StatusCodeStr = HttpHeaders + AsciiStrLen (HTTP_VERSION_STR) + 1; if (StatusCodeStr == NULL) { goto Error; } StatusCode = AsciiStrDecimalToUintn (StatusCodeStr); // // Remove the first line of HTTP message, e.g. "HTTP/1.1 200 OK\r\n". // Tmp = AsciiStrStr (HttpHeaders, HTTP_CRLF_STR); if (Tmp == NULL) { goto Error; } // // We could have response with just a HTTP message and no headers. For Example, // "100 Continue". In such cases, we would not want to unnecessarily call a Parse // method. A "\r\n" following Tmp string again would indicate an end. Compare and // set SizeofHeaders to 0. // Tmp = Tmp + AsciiStrLen (HTTP_CRLF_STR); if (CompareMem (Tmp, HTTP_CRLF_STR, AsciiStrLen (HTTP_CRLF_STR)) == 0) { SizeofHeaders = 0; } else { SizeofHeaders = SizeofHeaders - (Tmp - HttpHeaders); } HttpMsg->Data.Response->StatusCode = HttpMappingToStatusCode (StatusCode); HttpInstance->StatusCode = StatusCode; Status = EFI_NOT_READY; ValueInItem = NULL; // // In cases of PUT/POST, after an initial request-response pair, we would do a // continuous request without a response call. So, we would not do an insert of // TxToken. After we have sent the complete file, we will call a response to get // a final response from server. In such a case, we would not have any TxTokens. // Hence, check that case before doing a NetMapRemoveHead. // if (!NetMapIsEmpty (&HttpInstance->TxTokens)) { NetMapRemoveHead (&HttpInstance->TxTokens, (VOID**) &ValueInItem); if (ValueInItem == NULL) { goto Error; } // // The first Tx Token not transmitted yet, insert back and return error. // if (!ValueInItem->TcpWrap.IsTxDone) { goto Error2; } } if (SizeofHeaders != 0) { HeaderTmp = AllocateZeroPool (SizeofHeaders); if (HeaderTmp == NULL) { goto Error; } CopyMem (HeaderTmp, Tmp, SizeofHeaders); FreePool (HttpHeaders); HttpHeaders = HeaderTmp; // // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available. // if (mHttpUtilities == NULL) { Status = EFI_NOT_READY; goto Error; } // // Parse the HTTP header into array of key/value pairs. // Status = mHttpUtilities->Parse ( mHttpUtilities, HttpHeaders, SizeofHeaders, &HttpMsg->Headers, &HttpMsg->HeaderCount ); if (EFI_ERROR (Status)) { goto Error; } FreePool (HttpHeaders); HttpHeaders = NULL; // // Init message-body parser by header information. // Status = HttpInitMsgParser ( HttpInstance->Method, HttpMsg->Data.Response->StatusCode, HttpMsg->HeaderCount, HttpMsg->Headers, HttpBodyParserCallback, (VOID *) ValueInItem, &HttpInstance->MsgParser ); if (EFI_ERROR (Status)) { goto Error2; } // // Check whether we received a complete HTTP message. // if (HttpInstance->CacheBody != NULL) { Status = HttpParseMessageBody (HttpInstance->MsgParser, HttpInstance->CacheLen, HttpInstance->CacheBody); if (EFI_ERROR (Status)) { goto Error2; } if (HttpIsMessageComplete (HttpInstance->MsgParser)) { // // Free the MsgParse since we already have a full HTTP message. // HttpFreeMsgParser (HttpInstance->MsgParser); HttpInstance->MsgParser = NULL; } } } if ((HttpMsg->Body == NULL) || (HttpMsg->BodyLength == 0)) { Status = EFI_SUCCESS; goto Exit; } } // // Receive the response body. // BodyLen = 0; // // First check whether we cached some data. // if (HttpInstance->CacheBody != NULL) { // // Calculate the length of the cached data. // if (HttpInstance->NextMsg != NULL) { // // We have a cached HTTP message which includes a part of HTTP header of next message. // BodyLen = HttpInstance->NextMsg - (HttpInstance->CacheBody + HttpInstance->CacheOffset); } else { BodyLen = HttpInstance->CacheLen - HttpInstance->CacheOffset; } if (BodyLen > 0) { // // We have some cached data. Just copy the data and return. // if (HttpMsg->BodyLength < BodyLen) { CopyMem (HttpMsg->Body, HttpInstance->CacheBody + HttpInstance->CacheOffset, HttpMsg->BodyLength); HttpInstance->CacheOffset = HttpInstance->CacheOffset + HttpMsg->BodyLength; } else { // // Copy all cached data out. // CopyMem (HttpMsg->Body, HttpInstance->CacheBody + HttpInstance->CacheOffset, BodyLen); HttpInstance->CacheOffset = BodyLen + HttpInstance->CacheOffset; HttpMsg->BodyLength = BodyLen; if (HttpInstance->NextMsg == NULL) { // // There is no HTTP header of next message. Just free the cache buffer. // FreePool (HttpInstance->CacheBody); HttpInstance->CacheBody = NULL; HttpInstance->NextMsg = NULL; HttpInstance->CacheOffset = 0; } } // // Return since we aready received required data. // Status = EFI_SUCCESS; goto Exit; } if (BodyLen == 0 && HttpInstance->MsgParser == NULL) { // // We received a complete HTTP message, and we don't have more data to return to caller. // HttpMsg->BodyLength = 0; Status = EFI_SUCCESS; goto Exit; } } ASSERT (HttpInstance->MsgParser != NULL); if (HttpInstance->TimeoutEvent == NULL) { // // Create TimeoutEvent for response // Status = gBS->CreateEvent ( EVT_TIMER, TPL_CALLBACK, NULL, NULL, &HttpInstance->TimeoutEvent ); if (EFI_ERROR (Status)) { goto Error; } } // // Start the timer, and wait Timeout seconds to receive the body packet. // Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_RESPONSE_TIMEOUT * TICKS_PER_SECOND); if (EFI_ERROR (Status)) { goto Error; } // // We still need receive more data when there is no cache data and MsgParser is not NULL; // Status = HttpTcpReceiveBody (Wrap, HttpMsg, HttpInstance->TimeoutEvent); gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0); if (EFI_ERROR (Status)) { goto Error; } FreePool (Wrap); return Status; Exit: Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken); if (Item != NULL) { NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL); } if (HttpInstance->StatusCode >= HTTP_ERROR_OR_NOT_SUPPORT_STATUS_CODE) { Token->Status = EFI_HTTP_ERROR; } else { Token->Status = Status; } gBS->SignalEvent (Token->Event); HttpCloseTcpRxEvent (Wrap); FreePool (Wrap); return Status; Error2: NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem); Error: HttpTcpTokenCleanup (Wrap); if (HttpHeaders != NULL) { FreePool (HttpHeaders); } if (HttpMsg->Headers != NULL) { FreePool (HttpMsg->Headers); } if (HttpInstance->CacheBody != NULL) { FreePool (HttpInstance->CacheBody); HttpInstance->CacheBody = NULL; } if (HttpInstance->StatusCode >= HTTP_ERROR_OR_NOT_SUPPORT_STATUS_CODE) { Token->Status = EFI_HTTP_ERROR; } else { Token->Status = Status; } gBS->SignalEvent (Token->Event); return Status; }
/** This function delete and build multi-instance device path for specified type of console device. This function clear the EFI variable defined by ConsoleName and gEfiGlobalVariableGuid. It then build the multi-instance device path by appending the device path of the Console (In/Out/Err) instance in ConsoleMenu. Then it scan all corresponding console device by scanning Terminal (built from device supporting Serial I/O instances) devices in TerminalMenu. At last, it save a EFI variable specifed by ConsoleName and gEfiGlobalVariableGuid. @param ConsoleName The name for the console device type. They are usually "ConIn", "ConOut" and "ErrOut". @param ConsoleMenu The console memu which is a list of console devices. @param UpdatePageId The flag specifying which type of console device to be processed. @retval EFI_SUCCESS The function complete successfully. @return The EFI variable can not be saved. See gRT->SetVariable for detail return information. **/ EFI_STATUS Var_UpdateConsoleOption ( IN UINT16 *ConsoleName, IN BM_MENU_OPTION *ConsoleMenu, IN UINT16 UpdatePageId ) { EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; BM_MENU_ENTRY *NewMenuEntry; BM_CONSOLE_CONTEXT *NewConsoleContext; BM_TERMINAL_CONTEXT *NewTerminalContext; EFI_STATUS Status; VENDOR_DEVICE_PATH Vendor; EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath; UINTN Index; ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid); if (ConDevicePath != NULL) { EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid); FreePool (ConDevicePath); ConDevicePath = NULL; }; // // First add all console input device from console input menu // for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; if (NewConsoleContext->IsActive) { ConDevicePath = AppendDevicePathInstance ( ConDevicePath, NewConsoleContext->DevicePath ); } } for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; if (((NewTerminalContext->IsConIn != 0) && (UpdatePageId == FORM_CON_IN_ID)) || ((NewTerminalContext->IsConOut != 0) && (UpdatePageId == FORM_CON_OUT_ID)) || ((NewTerminalContext->IsStdErr != 0) && (UpdatePageId == FORM_CON_ERR_ID)) ) { Vendor.Header.Type = MESSAGING_DEVICE_PATH; Vendor.Header.SubType = MSG_VENDOR_DP; ASSERT (NewTerminalContext->TerminalType < (sizeof (TerminalTypeGuid) / sizeof (TerminalTypeGuid[0]))); CopyMem ( &Vendor.Guid, &TerminalTypeGuid[NewTerminalContext->TerminalType], sizeof (EFI_GUID) ); SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); TerminalDevicePath = AppendDevicePathNode ( NewTerminalContext->DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Vendor ); ASSERT (TerminalDevicePath != NULL); ChangeTerminalDevicePath (&TerminalDevicePath, TRUE); ConDevicePath = AppendDevicePathInstance ( ConDevicePath, TerminalDevicePath ); } } if (ConDevicePath != NULL) { Status = gRT->SetVariable ( ConsoleName, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, GetDevicePathSize (ConDevicePath), ConDevicePath ); if (EFI_ERROR (Status)) { return Status; } } return EFI_SUCCESS; }
/** This function will save confidential information to lockbox. @param Guid the guid to identify the confidential information @param Buffer the address of the confidential information @param Length the length of the confidential information @retval RETURN_SUCCESS the information is saved successfully. @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0 @retval RETURN_ALREADY_STARTED the requested GUID already exist. @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information. @retval RETURN_ACCESS_DENIED it is too late to invoke this interface @retval RETURN_NOT_STARTED it is too early to invoke this interface @retval RETURN_UNSUPPORTED the service is not supported by implementaion. **/ RETURN_STATUS EFIAPI SaveLockBox ( IN GUID *Guid, IN VOID *Buffer, IN UINTN Length ) { SMM_LOCK_BOX_DATA *LockBox; EFI_PHYSICAL_ADDRESS SmramBuffer; EFI_STATUS Status; LIST_ENTRY *LockBoxQueue; DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Enter\n")); // // Basic check // if ((Guid == NULL) || (Buffer == NULL) || (Length == 0)) { DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_INVALID_PARAMETER)); return EFI_INVALID_PARAMETER; } // // Find LockBox // LockBox = InternalFindLockBoxByGuid (Guid); if (LockBox != NULL) { DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_ALREADY_STARTED)); return EFI_ALREADY_STARTED; } // // Allocate SMRAM buffer // Status = gSmst->SmmAllocatePages ( AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (Length), &SmramBuffer ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES)); return EFI_OUT_OF_RESOURCES; } // // Allocate LockBox // Status = gSmst->SmmAllocatePool ( EfiRuntimeServicesData, sizeof(*LockBox), (VOID **)&LockBox ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { gSmst->SmmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length)); DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES)); return EFI_OUT_OF_RESOURCES; } // // Save data // CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)Buffer, Length); // // Insert LockBox to queue // LockBox->Signature = SMM_LOCK_BOX_DATA_SIGNATURE; CopyMem (&LockBox->Guid, Guid, sizeof(EFI_GUID)); LockBox->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; LockBox->Length = (UINT64)Length; LockBox->Attributes = 0; LockBox->SmramBuffer = SmramBuffer; DEBUG (( EFI_D_INFO, "LockBoxGuid - %g, SmramBuffer - 0x%lx, Length - 0x%lx\n", &LockBox->Guid, LockBox->SmramBuffer, LockBox->Length )); LockBoxQueue = InternalGetLockBoxQueue (); ASSERT (LockBoxQueue != NULL); InsertTailList (LockBoxQueue, &LockBox->Link); // // Done // DEBUG ((EFI_D_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_SUCCESS)); return EFI_SUCCESS; }
/** Measure GPT table data into TPM log. @param TcgProtocol Pointer to the located TCG protocol instance. @param GptHandle Handle that GPT partition was installed. @retval EFI_SUCCESS Successfully measure GPT table. @retval EFI_UNSUPPORTED Not support GPT table on the given handle. @retval EFI_DEVICE_ERROR Can't get GPT table because device error. @retval EFI_OUT_OF_RESOURCES No enough resource to measure GPT table. @retval other error value **/ EFI_STATUS EFIAPI TcgMeasureGptTable ( IN EFI_TCG_PROTOCOL *TcgProtocol, IN EFI_HANDLE GptHandle ) { EFI_STATUS Status; EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_DISK_IO_PROTOCOL *DiskIo; EFI_PARTITION_TABLE_HEADER *PrimaryHeader; EFI_PARTITION_ENTRY *PartitionEntry; UINT8 *EntryPtr; UINTN NumberOfPartition; UINT32 Index; TCG_PCR_EVENT *TcgEvent; EFI_GPT_DATA *GptData; UINT32 EventSize; UINT32 EventNumber; EFI_PHYSICAL_ADDRESS EventLogLastEntry; if (mMeasureGptCount > 0) { return EFI_SUCCESS; } Status = gBS->HandleProtocol (GptHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } Status = gBS->HandleProtocol (GptHandle, &gEfiDiskIoProtocolGuid, (VOID**)&DiskIo); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } // // Read the EFI Partition Table Header // PrimaryHeader = (EFI_PARTITION_TABLE_HEADER *) AllocatePool (BlockIo->Media->BlockSize); if (PrimaryHeader == NULL) { return EFI_OUT_OF_RESOURCES; } Status = DiskIo->ReadDisk ( DiskIo, BlockIo->Media->MediaId, 1 * BlockIo->Media->BlockSize, BlockIo->Media->BlockSize, (UINT8 *)PrimaryHeader ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "Failed to Read Partition Table Header!\n")); FreePool (PrimaryHeader); return EFI_DEVICE_ERROR; } // // Read the partition entry. // EntryPtr = (UINT8 *)AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); if (EntryPtr == NULL) { FreePool (PrimaryHeader); return EFI_OUT_OF_RESOURCES; } Status = DiskIo->ReadDisk ( DiskIo, BlockIo->Media->MediaId, MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry, EntryPtr ); if (EFI_ERROR (Status)) { FreePool (PrimaryHeader); FreePool (EntryPtr); return EFI_DEVICE_ERROR; } // // Count the valid partition // PartitionEntry = (EFI_PARTITION_ENTRY *)EntryPtr; NumberOfPartition = 0; for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) { NumberOfPartition++; } PartitionEntry++; } // // Parepare Data for Measurement // EventSize = (UINT32)(sizeof (EFI_GPT_DATA) - sizeof (GptData->Partitions) + NumberOfPartition * PrimaryHeader->SizeOfPartitionEntry); TcgEvent = (TCG_PCR_EVENT *) AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT)); if (TcgEvent == NULL) { FreePool (PrimaryHeader); FreePool (EntryPtr); return EFI_OUT_OF_RESOURCES; } TcgEvent->PCRIndex = 5; TcgEvent->EventType = EV_EFI_GPT_EVENT; TcgEvent->EventSize = EventSize; GptData = (EFI_GPT_DATA *) TcgEvent->Event; // // Copy the EFI_PARTITION_TABLE_HEADER and NumberOfPartition // CopyMem ((UINT8 *)GptData, (UINT8*)PrimaryHeader, sizeof (EFI_PARTITION_TABLE_HEADER)); GptData->NumberOfPartitions = NumberOfPartition; // // Copy the valid partition entry // PartitionEntry = (EFI_PARTITION_ENTRY*)EntryPtr; NumberOfPartition = 0; for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { if (!CompareGuid (&PartitionEntry->PartitionTypeGUID, &mZeroGuid)) { CopyMem ( (UINT8 *)&GptData->Partitions + NumberOfPartition * sizeof (EFI_PARTITION_ENTRY), (UINT8 *)PartitionEntry, sizeof (EFI_PARTITION_ENTRY) ); NumberOfPartition++; } PartitionEntry++; } // // Measure the GPT data // EventNumber = 1; Status = TcgProtocol->HashLogExtendEvent ( TcgProtocol, (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) GptData, (UINT64) TcgEvent->EventSize, TPM_ALG_SHA, TcgEvent, &EventNumber, &EventLogLastEntry ); if (!EFI_ERROR (Status)) { mMeasureGptCount++; } FreePool (PrimaryHeader); FreePool (EntryPtr); FreePool (TcgEvent); return Status; }
/** Open a device named by PathName. The PathName includes a device name and path separated by a :. See file header for more details on the PathName syntax. There is no checking to prevent a file from being opened more than one type. SectionType is only used to open an FV. Each file in an FV contains multiple sections and only the SectionType section is opened. For any file that is opened with EfiOpen() must be closed with EfiClose(). @param PathName Path to parse to open @param OpenMode Same as EFI_FILE.Open() @param SectionType Section in FV to open. @return NULL Open failed @return Valid EFI_OPEN_FILE handle **/ EFI_OPEN_FILE * EfiOpen ( IN CHAR8 *PathName, IN CONST UINT64 OpenMode, IN CONST EFI_SECTION_TYPE SectionType ) { EFI_STATUS Status; EFI_OPEN_FILE *File; EFI_OPEN_FILE FileData; UINTN StrLen; UINTN FileStart; UINTN DevNumber = 0; EFI_OPEN_FILE_GUARD *GuardFile; BOOLEAN VolumeNameMatch; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN Size; EFI_IP_ADDRESS Ip; CHAR8 *CwdPlusPathName; UINTN Index; EFI_SECTION_TYPE ModifiedSectionType; EblUpdateDeviceLists (); File = &FileData; ZeroMem (File, sizeof (EFI_OPEN_FILE)); StrLen = AsciiStrSize (PathName); if (StrLen <= 1) { // Smallest valid path is 1 char and a null return NULL; } for (FileStart = 0; FileStart < StrLen; FileStart++) { if (PathName[FileStart] == ':') { FileStart++; break; } } // // Matching volume name has precedence over handle based names // VolumeNameMatch = EblMatchVolumeName (PathName, FileStart, &DevNumber); if (!VolumeNameMatch) { if (FileStart == StrLen) { // No Volume name or device name, so try Current Working Directory if (gCwd == NULL) { // No CWD return NULL; } // We could add a current working directory concept CwdPlusPathName = AllocatePool (AsciiStrSize (gCwd) + AsciiStrSize (PathName)); if (CwdPlusPathName == NULL) { return NULL; } if ((PathName[0] == '/') || (PathName[0] == '\\')) { // PathName starts in / so this means we go to the root of the device in the CWD. CwdPlusPathName[0] = '\0'; for (FileStart = 0; gCwd[FileStart] != '\0'; FileStart++) { CwdPlusPathName[FileStart] = gCwd[FileStart]; if (gCwd[FileStart] == ':') { FileStart++; CwdPlusPathName[FileStart] = '\0'; break; } } } else { AsciiStrCpy (CwdPlusPathName, gCwd); StrLen = AsciiStrLen (gCwd); if ((*PathName != '/') && (*PathName != '\\') && (gCwd[StrLen-1] != '/') && (gCwd[StrLen-1] != '\\')) { AsciiStrCat (CwdPlusPathName, "\\"); } } AsciiStrCat (CwdPlusPathName, PathName); if (AsciiStrStr (CwdPlusPathName, ":") == NULL) { // Extra error check to make sure we don't recurse and blow stack return NULL; } File = EfiOpen (CwdPlusPathName, OpenMode, SectionType); FreePool (CwdPlusPathName); return File; } DevNumber = EblConvertDevStringToNumber ((CHAR8 *)PathName); } File->DeviceName = AllocatePool (StrLen); AsciiStrCpy (File->DeviceName, PathName); File->DeviceName[FileStart - 1] = '\0'; File->FileName = &File->DeviceName[FileStart]; if (File->FileName[0] == '\0') { // if it is just a file name use / as root File->FileName = "\\"; } // // Use best match algorithm on the dev names so we only need to look at the // first few charters to match the full device name. Short name forms are // legal from the caller. // Status = EFI_SUCCESS; if (*PathName == 'f' || *PathName == 'F' || VolumeNameMatch) { if (PathName[1] == 's' || PathName[1] == 'S' || VolumeNameMatch) { if (DevNumber >= mFsCount) { goto ErrorExit; } File->Type = EfiOpenFileSystem; File->EfiHandle = mFs[DevNumber]; Status = EblFileDevicePath (File, &PathName[FileStart], OpenMode); } else if (PathName[1] == 'v' || PathName[1] == 'V') { if (DevNumber >= mFvCount) { goto ErrorExit; } File->Type = EfiOpenFirmwareVolume; File->EfiHandle = mFv[DevNumber]; if ((PathName[FileStart] == '/') || (PathName[FileStart] == '\\')) { // Skip leading / as its not really needed for the FV since no directories are supported FileStart++; } // Check for 2nd : ModifiedSectionType = SectionType; for (Index = FileStart; PathName[Index] != '\0'; Index++) { if (PathName[Index] == ':') { // Support fv0:\DxeCore:0x10 // This means open the PE32 Section of the file ModifiedSectionType = (EFI_SECTION_TYPE)AsciiStrHexToUintn (&PathName[Index + 1]); PathName[Index] = '\0'; } } File->FvSectionType = ModifiedSectionType; Status = EblFvFileDevicePath (File, &PathName[FileStart], ModifiedSectionType); } } else if ((*PathName == 'A') || (*PathName == 'a')) { // Handle a:0x10000000:0x1234 address form a:ADDRESS:SIZE File->Type = EfiOpenMemoryBuffer; // 1st colon is at PathName[FileStart - 1] File->Buffer = (VOID *)AsciiStrHexToUintn (&PathName[FileStart]); // Find 2nd colon while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { FileStart++; } // If we ran out of string, there's no extra data if (PathName[FileStart] == '\0') { File->Size = 0; } else { File->Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); } // if there's no number after the second colon, default // the end of memory if (File->Size == 0) { File->Size = (UINTN)(0 - (UINTN)File->Buffer); } File->MaxPosition = File->Size; File->BaseOffset = (UINTN)File->Buffer; } else if (*PathName== 'l' || *PathName == 'L') { if (DevNumber >= mLoadFileCount) { goto ErrorExit; } File->Type = EfiOpenLoadFile; File->EfiHandle = mLoadFile[DevNumber]; Status = gBS->HandleProtocol (File->EfiHandle, &gEfiLoadFileProtocolGuid, (VOID **)&File->LoadFile); if (EFI_ERROR (Status)) { goto ErrorExit; } Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath); if (EFI_ERROR (Status)) { goto ErrorExit; } File->DevicePath = DuplicateDevicePath (DevicePath); } else if (*PathName == 'b' || *PathName == 'B') { // Handle b#:0x10000000:0x1234 address form b#:ADDRESS:SIZE if (DevNumber >= mBlkIoCount) { goto ErrorExit; } File->Type = EfiOpenBlockIo; File->EfiHandle = mBlkIo[DevNumber]; EblFileDevicePath (File, "", OpenMode); // 1st colon is at PathName[FileStart - 1] File->DiskOffset = AsciiStrHexToUintn (&PathName[FileStart]); // Find 2nd colon while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { FileStart++; } // If we ran out of string, there's no extra data if (PathName[FileStart] == '\0') { Size = 0; } else { Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); } // if a zero size is passed in (or the size is left out entirely), // go to the end of the device. if (Size == 0) { File->Size = File->Size - File->DiskOffset; } else { File->Size = Size; } File->MaxPosition = File->Size; File->BaseOffset = File->DiskOffset; } else if ((*PathName) >= '0' && (*PathName <= '9')) { // Get current IP address Status = EblGetCurrentIpAddress (&Ip); if (EFI_ERROR(Status)) { AsciiPrint("Device IP Address is not configured.\n"); goto ErrorExit; } // Parse X.X.X.X:Filename, only support IPv4 TFTP for now... File->Type = EfiOpenTftp; File->IsDirty = FALSE; File->IsBufferValid = FALSE; Status = ConvertIpStringToEfiIp (PathName, &File->ServerIp); } if (EFI_ERROR (Status)) { goto ErrorExit; } GuardFile = (EFI_OPEN_FILE_GUARD *)AllocateZeroPool (sizeof (EFI_OPEN_FILE_GUARD)); if (GuardFile == NULL) { goto ErrorExit; } GuardFile->Header = EFI_OPEN_FILE_GUARD_HEADER; CopyMem (&(GuardFile->File), &FileData, sizeof (EFI_OPEN_FILE)); GuardFile->Footer = EFI_OPEN_FILE_GUARD_FOOTER; return &(GuardFile->File); ErrorExit: FreePool (File->DeviceName); return NULL; }
/** Function for 'comp' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunComp ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; CHAR16 *FileName1; CHAR16 *FileName2; CONST CHAR16 *TempParam; SHELL_STATUS ShellStatus; SHELL_FILE_HANDLE FileHandle1; SHELL_FILE_HANDLE FileHandle2; UINT64 Size1; UINT64 Size2; UINT64 DifferentBytes; UINT64 DifferentCount; UINT8 DiffPointNumber; UINT8 OneByteFromFile1; UINT8 OneByteFromFile2; UINT8 *DataFromFile1; UINT8 *DataFromFile2; UINTN InsertPosition1; UINTN InsertPosition2; UINTN DataSizeFromFile1; UINTN DataSizeFromFile2; UINTN TempAddress; UINTN Index; UINTN DiffPointAddress; READ_STATUS ReadStatus; ShellStatus = SHELL_SUCCESS; Status = EFI_SUCCESS; FileName1 = NULL; FileName2 = NULL; FileHandle1 = NULL; FileHandle2 = NULL; DataFromFile1 = NULL; DataFromFile2 = NULL; ReadStatus = OutOfDiffPoint; DifferentCount = 10; DifferentBytes = 4; DiffPointNumber = 0; InsertPosition1 = 0; InsertPosition2 = 0; TempAddress = 0; DiffPointAddress = 0; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); // ASSERT_EFI_ERROR(Status); if (EFI_ERROR(Status)) { return SHELL_UNSUPPORTED; } Status = CommandInit(); // ASSERT_EFI_ERROR(Status); if (EFI_ERROR(Status)) { return SHELL_UNSUPPORTED; } // // parse the command line // Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"comp", ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } /* else { ASSERT(FALSE); } */ } else { if (ShellCommandLineGetCount(Package) > 3) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"comp"); ShellStatus = SHELL_INVALID_PARAMETER; } else if (ShellCommandLineGetCount(Package) < 3) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"comp"); ShellStatus = SHELL_INVALID_PARAMETER; } else { TempParam = ShellCommandLineGetRawValue(Package, 1); ASSERT(TempParam != NULL); FileName1 = ShellFindFilePath(TempParam); if (FileName1 == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); ShellStatus = SHELL_NOT_FOUND; } else { Status = ShellOpenFileByName(FileName1, &FileHandle1, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); ShellStatus = SHELL_NOT_FOUND; } } TempParam = ShellCommandLineGetRawValue(Package, 2); ASSERT(TempParam != NULL); FileName2 = ShellFindFilePath(TempParam); if (FileName2 == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); ShellStatus = SHELL_NOT_FOUND; } else { Status = ShellOpenFileByName(FileName2, &FileHandle2, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam); ShellStatus = SHELL_NOT_FOUND; } } if (ShellStatus == SHELL_SUCCESS) { Status = gEfiShellProtocol->GetFileSize(FileHandle1, &Size1); ASSERT_EFI_ERROR(Status); Status = gEfiShellProtocol->GetFileSize(FileHandle2, &Size2); ASSERT_EFI_ERROR(Status); if (ShellCommandLineGetFlag (Package, L"-n")) { TempParam = ShellCommandLineGetValue (Package, L"-n"); if (TempParam == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"comp", L"-n"); ShellStatus = SHELL_INVALID_PARAMETER; } else { if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)TempParam, L"all") == 0) { DifferentCount = MAX_UINTN; } else { Status = ShellConvertStringToUint64 (TempParam, &DifferentCount, FALSE, TRUE); if (EFI_ERROR(Status) || DifferentCount == 0) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"comp", TempParam, L"-n"); ShellStatus = SHELL_INVALID_PARAMETER; } } } } if (ShellCommandLineGetFlag (Package, L"-s")) { TempParam = ShellCommandLineGetValue (Package, L"-s"); if (TempParam == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"comp", L"-s"); ShellStatus = SHELL_INVALID_PARAMETER; } else { Status = ShellConvertStringToUint64 (TempParam, &DifferentBytes, FALSE, TRUE); if (EFI_ERROR(Status) || DifferentBytes == 0) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"comp", TempParam, L"-s"); ShellStatus = SHELL_INVALID_PARAMETER; } else { if (DifferentBytes > MAX (Size1, Size2)) { DifferentBytes = MAX (Size1, Size2); } } } } } if (ShellStatus == SHELL_SUCCESS) { DataFromFile1 = AllocateZeroPool ((UINTN)DifferentBytes); DataFromFile2 = AllocateZeroPool ((UINTN)DifferentBytes); if (DataFromFile1 == NULL || DataFromFile2 == NULL) { ShellStatus = SHELL_OUT_OF_RESOURCES; SHELL_FREE_NON_NULL (DataFromFile1); SHELL_FREE_NON_NULL (DataFromFile2); } } if (ShellStatus == SHELL_SUCCESS) { while (DiffPointNumber < DifferentCount) { DataSizeFromFile1 = 1; DataSizeFromFile2 = 1; OneByteFromFile1 = 0; OneByteFromFile2 = 0; Status = gEfiShellProtocol->ReadFile (FileHandle1, &DataSizeFromFile1, &OneByteFromFile1); ASSERT_EFI_ERROR (Status); Status = gEfiShellProtocol->ReadFile (FileHandle2, &DataSizeFromFile2, &OneByteFromFile2); ASSERT_EFI_ERROR (Status); TempAddress++; // // 1.When end of file and no chars in DataFromFile buffer, then break while. // 2.If no more char in File1 or File2, The ReadStatus is InPrevDiffPoint forever. // So the previous different point is the last one, then break the while block. // if ( (DataSizeFromFile1 == 0 && InsertPosition1 == 0 && DataSizeFromFile2 == 0 && InsertPosition2 == 0) || (ReadStatus == InPrevDiffPoint && (DataSizeFromFile1 == 0 || DataSizeFromFile2 == 0)) ) { break; } if (ReadStatus == OutOfDiffPoint) { if (OneByteFromFile1 != OneByteFromFile2) { ReadStatus = InDiffPoint; DiffPointAddress = TempAddress; if (DataSizeFromFile1 == 1) { DataFromFile1[InsertPosition1++] = OneByteFromFile1; } if (DataSizeFromFile2 == 1) { DataFromFile2[InsertPosition2++] = OneByteFromFile2; } } } else if (ReadStatus == InDiffPoint) { if (DataSizeFromFile1 == 1) { DataFromFile1[InsertPosition1++] = OneByteFromFile1; } if (DataSizeFromFile2 == 1) { DataFromFile2[InsertPosition2++] = OneByteFromFile2; } } else if (ReadStatus == InPrevDiffPoint) { if (OneByteFromFile1 == OneByteFromFile2) { ReadStatus = OutOfDiffPoint; } } // // ReadStatus should be always equal InDiffPoint. // if ( InsertPosition1 == DifferentBytes || InsertPosition2 == DifferentBytes || (DataSizeFromFile1 == 0 && DataSizeFromFile2 == 0) ) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_COMP_DIFFERENCE_POINT), gShellDebug1HiiHandle, ++DiffPointNumber); PrintDifferentPoint (FileName1, L"File1", DataFromFile1, InsertPosition1, DiffPointAddress, DifferentBytes); PrintDifferentPoint (FileName2, L"File2", DataFromFile2, InsertPosition2, DiffPointAddress, DifferentBytes); // // One of two buffuers is empty, it means this is the last different point. // if (InsertPosition1 == 0 || InsertPosition2 == 0) { break; } for (Index = 1; Index < InsertPosition1 && Index < InsertPosition2; Index++) { if (DataFromFile1[Index] == DataFromFile2[Index]) { ReadStatus = OutOfDiffPoint; break; } } if (ReadStatus == OutOfDiffPoint) { // // Try to find a new different point in the rest of DataFromFile. // for (; Index < MAX (InsertPosition1,InsertPosition2); Index++) { if (DataFromFile1[Index] != DataFromFile2[Index]) { ReadStatus = InDiffPoint; DiffPointAddress += Index; break; } } } else { // // Doesn't find a new different point, still in the same different point. // ReadStatus = InPrevDiffPoint; } CopyMem (DataFromFile1, DataFromFile1 + Index, InsertPosition1 - Index); CopyMem (DataFromFile2, DataFromFile2 + Index, InsertPosition2 - Index); SetMem (DataFromFile1 + InsertPosition1 - Index, (UINTN)DifferentBytes - InsertPosition1 + Index, 0); SetMem (DataFromFile2 + InsertPosition2 - Index, (UINTN)DifferentBytes - InsertPosition2 + Index, 0); InsertPosition1 -= Index; InsertPosition2 -= Index; } } SHELL_FREE_NON_NULL (DataFromFile1); SHELL_FREE_NON_NULL (DataFromFile2); if (DiffPointNumber == 0) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_PASS), gShellDebug1HiiHandle); } else { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_FAIL), gShellDebug1HiiHandle); } } } ShellCommandLineFreeVarList (Package); } SHELL_FREE_NON_NULL(FileName1); SHELL_FREE_NON_NULL(FileName2); if (FileHandle1 != NULL) { gEfiShellProtocol->CloseFile(FileHandle1); } if (FileHandle2 != NULL) { gEfiShellProtocol->CloseFile(FileHandle2); } return (ShellStatus); }
/** This command defines the attributes of an NV Index and causes the TPM to reserve space to hold the data associated with the index. If a definition already exists at the index, the TPM will return TPM_RC_NV_DEFINED. @param[in] AuthHandle TPM_RH_OWNER or TPM_RH_PLATFORM+{PP}. @param[in] AuthSession Auth Session context @param[in] Auth The authorization data. @param[in] NvPublic The public area of the index. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. @retval EFI_ALREADY_STARTED The command was returned successfully, but NvIndex is already defined. **/ EFI_STATUS EFIAPI Tpm2NvDefineSpace ( IN TPMI_RH_PROVISION AuthHandle, IN TPMS_AUTH_COMMAND *AuthSession, OPTIONAL IN TPM2B_AUTH *Auth, IN TPM2B_NV_PUBLIC *NvPublic ) { EFI_STATUS Status; TPM2_NV_DEFINESPACE_COMMAND SendBuffer; TPM2_NV_DEFINESPACE_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT16 NvPublicSize; UINT8 *Buffer; UINT32 SessionInfoSize; TPM_RC ResponseCode; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_DefineSpace); SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); // // Add in Auth session // Buffer = (UINT8 *)&SendBuffer.AuthSession; // sessionInfoSize SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); Buffer += SessionInfoSize; SendBuffer.AuthSessionSize = SwapBytes32(SessionInfoSize); // // IndexAuth // WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16(Auth->size)); Buffer += sizeof(UINT16); CopyMem(Buffer, Auth->buffer, Auth->size); Buffer += Auth->size; // // NvPublic // NvPublicSize = NvPublic->size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublicSize)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (NvPublic->nvPublic.nvIndex)); Buffer += sizeof(UINT32); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.nameAlg)); Buffer += sizeof(UINT16); WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); Buffer += sizeof(UINT32); WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.authPolicy.size)); Buffer += sizeof(UINT16); CopyMem (Buffer, NvPublic->nvPublic.authPolicy.buffer, NvPublic->nvPublic.authPolicy.size); Buffer += NvPublic->nvPublic.authPolicy.size; WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (NvPublic->nvPublic.dataSize)); Buffer += sizeof(UINT16); SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); if (ResponseCode != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2NvDefineSpace - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); } switch (ResponseCode) { case TPM_RC_SUCCESS: // return data break; case TPM_RC_SIZE + RC_NV_DefineSpace_publicInfo: case TPM_RC_SIZE + RC_NV_DefineSpace_auth: return EFI_BAD_BUFFER_SIZE; case TPM_RC_ATTRIBUTES: case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_publicInfo: return EFI_UNSUPPORTED; case TPM_RC_ATTRIBUTES + RC_NV_DefineSpace_authHandle: return EFI_INVALID_PARAMETER; case TPM_RC_NV_DEFINED: return EFI_ALREADY_STARTED; case TPM_RC_VALUE + RC_NV_DefineSpace_publicInfo: case TPM_RC_VALUE + RC_NV_DefineSpace_authHandle: return EFI_INVALID_PARAMETER; case TPM_RC_NV_SPACE: return EFI_OUT_OF_RESOURCES; default: return EFI_DEVICE_ERROR; } return EFI_SUCCESS; }
/** Initialize debug agent. This function is used to set up debug enviroment for source level debug in SMM code. If InitFlag is DEBUG_AGENT_INIT_SMM, it will overirde IDT table entries and initialize debug port. It will get debug agent Mailbox from GUIDed HOB, it it exists, debug agent wiil copied it into the local Mailbox in SMM space. it will overirde IDT table entries and initialize debug port. Context will be NULL. If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug Registers and get local Mailbox in SMM space. Context will be NULL. If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug Registers. Context will be NULL. @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 ) { EFI_STATUS Status; UINT64 DebugPortHandle; IA32_IDT_GATE_DESCRIPTOR IdtEntry[33]; IA32_DESCRIPTOR IdtDescriptor; IA32_DESCRIPTOR *Ia32Idtr; IA32_IDT_ENTRY *Ia32IdtEntry; IA32_DESCRIPTOR Idtr; UINT16 IdtEntryCount; DEBUG_AGENT_MAILBOX *Mailbox; UINT64 *MailboxLocation; switch (InitFlag) { case DEBUG_AGENT_INIT_SMM: // // Install configuration table for persisted vector handoff info // Status = gSmst->SmmInstallConfigurationTable ( gSmst, &gEfiVectorHandoffTableGuid, (VOID *) &mVectorHandoffInfoDebugAgent[0], sizeof (EFI_VECTOR_HANDOFF_INFO) * mVectorHandoffInfoCount ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n")); CpuDeadLoop (); } // // Check if Debug Agent initialized in DXE phase // Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox); if (Status == EFI_SUCCESS && Mailbox != NULL) { VerifyMailboxChecksum (Mailbox); mMailboxPointer = Mailbox; break; } // // Check if Debug Agent initialized in SEC/PEI phase // Mailbox = GetMailboxFromHob (); if (Mailbox != NULL) { mMailboxPointer = Mailbox; break; } // // Debug Agent was not initialized before, use the local mailbox. // ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX)); Mailbox = &mLocalMailbox; // // Save original IDT entries // AsmReadIdtr (&IdtDescriptor); CopyMem (&IdtEntry, (VOID *)IdtDescriptor.Base, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR)); // // Initialized Debug Agent // InitializeDebugIdt (); DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle, NULL); UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle); mMailboxPointer = Mailbox; // // Trigger one software interrupt to inform HOST // TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE); SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1); // // Memory has been ready // if (IsHostAttached ()) { // // Trigger one software interrupt to inform HOST // TriggerSoftInterrupt (MEMORY_READY_SIGNATURE); } // // Find and report PE/COFF image info to HOST // FindAndReportModuleImageInfo (SIZE_4KB); // // Restore saved IDT entries // CopyMem ((VOID *)IdtDescriptor.Base, &IdtEntry, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR)); break; case DEBUG_AGENT_INIT_ENTER_SMI: SaveDebugRegister (); InitializeDebugIdt (); Mailbox = GetMailboxPointer (); if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) { // // If Debug Agent has been communicaton state with HOST, we need skip // any break points set in SMM, set Skip Breakpoint flag // mSkipBreakpoint = TRUE; } if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI) == 1) { if (mSkipBreakpoint) { // // Print warning message if ignore smm entry break // DebugPortWriteBuffer ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle, (UINT8 *)mWarningMsgIgnoreSmmEntryBreak, AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak) ); } else { // // If SMM entry break is set, SMM code will be break at here. // CpuBreakpoint (); } } break; case DEBUG_AGENT_INIT_EXIT_SMI: Mailbox = GetMailboxPointer (); // // Clear Skip Breakpoint flag // mSkipBreakpoint = FALSE; RestoreDebugRegister (); break; case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64: if (Context == NULL) { DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n")); CpuDeadLoop (); } else { Ia32Idtr = (IA32_DESCRIPTOR *) Context; Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base); MailboxLocation = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16)); mMailboxPointer = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation); VerifyMailboxChecksum (mMailboxPointer); // // 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); } InitializeDebugIdt (); // // Initialize Debug Timer hardware and enable interrupt. // InitializeDebugTimer (); EnableInterrupts (); FindAndReportModuleImageInfo (SIZE_4KB); } break; default: // // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this // Debug Agent library instance. // DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n")); CpuDeadLoop (); break; } }
/** function to insert string items into a list in the correct alphabetical place the resultant list is a double NULL terminated list of NULL terminated strings. upon successful return the memory must be caller freed (unless passed back in via a loop where it will get reallocated). @param[in,out] DestList double pointer to the list. may be NULL. @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL. @param[in] Item the item to insert. @retval EFI_SUCCESS the operation was successful. **/ EFI_STATUS EFIAPI LexicalInsertIntoList( IN OUT CHAR16 **DestList, IN OUT UINTN *DestSize, IN CONST CHAR16 *Item ) { CHAR16 *NewList; INTN LexicalMatchValue; CHAR16 *LexicalSpot; UINTN SizeOfAddedNameInBytes; // // If there are none, then just return with success // if (Item == NULL || *Item == CHAR_NULL || StrLen(Item)==0) { return (EFI_SUCCESS); } NewList = *DestList; SizeOfAddedNameInBytes = StrSize(Item); NewList = ReallocatePool(*DestSize, (*DestSize) + SizeOfAddedNameInBytes, NewList); (*DestSize) = (*DestSize) + SizeOfAddedNameInBytes; // // Find the correct spot in the list // for (LexicalSpot = NewList ; LexicalSpot != NULL && LexicalSpot < NewList + (*DestSize) ; LexicalSpot += StrLen(LexicalSpot) + 1 ) { // // Get Lexical Comparison Value between PrevCommand and Command list entry // LexicalMatchValue = gUnicodeCollation->StriColl ( gUnicodeCollation, (CHAR16 *)LexicalSpot, (CHAR16 *)Item ); // // The new item goes before this one. // if (LexicalMatchValue > 0 || StrLen(LexicalSpot) == 0) { if (StrLen(LexicalSpot) != 0) { // // Move this and all other items out of the way // CopyMem( LexicalSpot + (SizeOfAddedNameInBytes/sizeof(CHAR16)), LexicalSpot, (*DestSize) - SizeOfAddedNameInBytes - ((LexicalSpot - NewList) * sizeof(CHAR16)) ); } // // Stick this one in place // StrCpyS(LexicalSpot, SizeOfAddedNameInBytes/sizeof(CHAR16), Item); break; } } *DestList = NewList; return (EFI_SUCCESS); }
struct ISAPNP_Resource* CreateResource( struct ResourceIterator* iter, struct ISAPNPBase* res ) { struct ISAPNP_Resource* result = NULL; result = ISAPNP_AllocResource( iter->m_Resource->isapnpr_Type, res ); if( result == NULL ) { return NULL; } switch( iter->m_Resource->isapnpr_Type ) { case ISAPNP_NT_IRQ_RESOURCE: { struct ISAPNP_IRQResource* r; r = (struct ISAPNP_IRQResource*) result; // Make a copy of the iterators resource CopyMem( iter->m_Resource, r, sizeof( *r ) ); r->isapnpirqr_MinNode.mln_Succ = NULL; r->isapnpirqr_MinNode.mln_Pred = NULL; r->isapnpirqr_IRQMask = 1 << iter->m_IRQBit; break; } case ISAPNP_NT_DMA_RESOURCE: { struct ISAPNP_DMAResource* r; r = (struct ISAPNP_DMAResource*) result; // Make a copy of the iterators resource CopyMem( iter->m_Resource, r, sizeof( *r ) ); r->isapnpdmar_MinNode.mln_Succ = NULL; r->isapnpdmar_MinNode.mln_Pred = NULL; r->isapnpdmar_ChannelMask = 1 << iter->m_ChannelBit; break; } case ISAPNP_NT_IO_RESOURCE: { struct ISAPNP_IOResource* r; r = (struct ISAPNP_IOResource*) result; // Make a copy of the iterators resource CopyMem( iter->m_Resource, r, sizeof( *r ) ); r->isapnpior_MinNode.mln_Succ = NULL; r->isapnpior_MinNode.mln_Pred = NULL; r->isapnpior_MinBase = iter->m_Base; r->isapnpior_MaxBase = iter->m_Base; r->isapnpior_Alignment = 1; break; } case ISAPNP_NT_MEMORY_RESOURCE: default: ISAPNP_FreeResource( result, res ); result = NULL; break;; } return result; }
/** This is the entrypoint of PEIM @param FileHandle Handle of the file being invoked. @param PeiServices Describes the list of possible PEI Services. @retval EFI_SUCCESS if it completed successfully. **/ EFI_STATUS EFIAPI CbPeiEntryPoint ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; UINT64 LowMemorySize, HighMemorySize; UINT64 PeiMemSize = SIZE_64MB; // 64 MB EFI_PHYSICAL_ADDRESS PeiMemBase = 0; UINT32 RegEax; UINT8 PhysicalAddressBits; VOID* pCbHeader; VOID* pAcpiTable; UINT32 AcpiTableSize; VOID* pSmbiosTable; UINT32 SmbiosTableSize; SYSTEM_TABLE_INFO* pSystemTableInfo; FRAME_BUFFER_INFO FbInfo; FRAME_BUFFER_INFO* pFbInfo; ACPI_BOARD_INFO* pAcpiBoardInfo; UINTN PmCtrlRegBase, PmTimerRegBase, ResetRegAddress, ResetValue; UINTN PmEvtBase; UINTN PmGpeEnBase; LowMemorySize = 0; HighMemorySize = 0; Status = CbParseMemoryInfo (&LowMemorySize, &HighMemorySize); if (EFI_ERROR(Status)) return Status; DEBUG((EFI_D_ERROR, "LowMemorySize: 0x%lx.\n", LowMemorySize)); DEBUG((EFI_D_ERROR, "HighMemorySize: 0x%lx.\n", HighMemorySize)); ASSERT (LowMemorySize > 0); // // Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED // is intentionally omitted to prevent erasing of the coreboot header // record before it is processed by CbParseMemoryInfo. // BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ), (EFI_PHYSICAL_ADDRESS)(0), (UINT64)(0xA0000) ); BuildResourceDescriptorHob ( EFI_RESOURCE_MEMORY_RESERVED, ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ), (EFI_PHYSICAL_ADDRESS)(0xA0000), (UINT64)(0x60000) ); BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ), (EFI_PHYSICAL_ADDRESS)(0x100000), (UINT64) (LowMemorySize - 0x100000) ); if (HighMemorySize > 0) { BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ), (EFI_PHYSICAL_ADDRESS)(0x100000000ULL), HighMemorySize ); } // // Should be 64k aligned // PeiMemBase = (LowMemorySize - PeiMemSize) & (~(BASE_64KB - 1)); DEBUG((EFI_D_ERROR, "PeiMemBase: 0x%lx.\n", PeiMemBase)); DEBUG((EFI_D_ERROR, "PeiMemSize: 0x%lx.\n", PeiMemSize)); Status = PeiServicesInstallPeiMemory ( PeiMemBase, PeiMemSize ); ASSERT_EFI_ERROR (Status); // // Set cache on the physical memory // MtrrSetMemoryAttribute (BASE_1MB, LowMemorySize - BASE_1MB, CacheWriteBack); MtrrSetMemoryAttribute (0, 0xA0000, CacheWriteBack); // // Create Memory Type Information HOB // BuildGuidDataHob ( &gEfiMemoryTypeInformationGuid, mDefaultMemoryTypeInformation, sizeof(mDefaultMemoryTypeInformation) ); // // Create Fv hob // CbPeiReportRemainedFvs (); BuildMemoryAllocationHob ( PcdGet32 (PcdPayloadFdMemBase), PcdGet32 (PcdPayloadFdMemSize), EfiBootServicesData ); // // Build CPU memory space and IO space hob // AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); if (RegEax >= 0x80000008) { AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); PhysicalAddressBits = (UINT8) RegEax; } else { PhysicalAddressBits = 36; } // // Create a CPU hand-off information // BuildCpuHob (PhysicalAddressBits, 16); // // Report Local APIC range // BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB); // // Boot mode // Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION); ASSERT_EFI_ERROR (Status); Status = PeiServicesInstallPpi (mPpiBootMode); ASSERT_EFI_ERROR (Status); // // Set pcd to save the upper coreboot header in case the dxecore will // erase 0~4k memory // pCbHeader = NULL; if ((CbParseGetCbHeader (1, &pCbHeader) == RETURN_SUCCESS) && ((UINTN)pCbHeader > BASE_4KB)) { DEBUG((EFI_D_ERROR, "Actual Coreboot header: %p.\n", pCbHeader)); PcdSet32 (PcdCbHeaderPointer, (UINT32)(UINTN)pCbHeader); } // // Create guid hob for system tables like acpi table and smbios table // pAcpiTable = NULL; AcpiTableSize = 0; pSmbiosTable = NULL; SmbiosTableSize = 0; Status = CbParseAcpiTable (&pAcpiTable, &AcpiTableSize); if (EFI_ERROR (Status)) { // ACPI table is oblidgible DEBUG ((EFI_D_ERROR, "Failed to find the required acpi table\n")); ASSERT (FALSE); } CbParseSmbiosTable (&pSmbiosTable, &SmbiosTableSize); pSystemTableInfo = NULL; pSystemTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO)); ASSERT (pSystemTableInfo != NULL); pSystemTableInfo->AcpiTableBase = (UINT64) (UINTN)pAcpiTable; pSystemTableInfo->AcpiTableSize = AcpiTableSize; pSystemTableInfo->SmbiosTableBase = (UINT64) (UINTN)pSmbiosTable; pSystemTableInfo->SmbiosTableSize = SmbiosTableSize; DEBUG ((EFI_D_ERROR, "Detected Acpi Table at 0x%lx, length 0x%x\n", pSystemTableInfo->AcpiTableBase, pSystemTableInfo->AcpiTableSize)); DEBUG ((EFI_D_ERROR, "Detected Smbios Table at 0x%lx, length 0x%x\n", pSystemTableInfo->SmbiosTableBase, pSystemTableInfo->SmbiosTableSize)); DEBUG ((EFI_D_ERROR, "Create system table info guid hob\n")); // // Create guid hob for acpi board information // Status = CbParseFadtInfo (&PmCtrlRegBase, &PmTimerRegBase, &ResetRegAddress, &ResetValue, &PmEvtBase, &PmGpeEnBase); ASSERT_EFI_ERROR (Status); pAcpiBoardInfo = NULL; pAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO)); ASSERT (pAcpiBoardInfo != NULL); pAcpiBoardInfo->PmCtrlRegBase = (UINT64)PmCtrlRegBase; pAcpiBoardInfo->PmTimerRegBase = (UINT64)PmTimerRegBase; pAcpiBoardInfo->ResetRegAddress = (UINT64)ResetRegAddress; pAcpiBoardInfo->ResetValue = (UINT8)ResetValue; pAcpiBoardInfo->PmEvtBase = (UINT64)PmEvtBase; pAcpiBoardInfo->PmGpeEnBase = (UINT64)PmGpeEnBase; DEBUG ((EFI_D_ERROR, "Create acpi board info guid hob\n")); // // Create guid hob for frame buffer information // ZeroMem (&FbInfo, sizeof (FRAME_BUFFER_INFO)); Status = CbParseFbInfo (&FbInfo); if (!EFI_ERROR (Status)) { pFbInfo = BuildGuidHob (&gUefiFrameBufferInfoGuid, sizeof (FRAME_BUFFER_INFO)); ASSERT (pSystemTableInfo != NULL); CopyMem (pFbInfo, &FbInfo, sizeof (FRAME_BUFFER_INFO)); DEBUG ((EFI_D_ERROR, "Create frame buffer info guid hob\n")); } // // Mask off all legacy 8259 interrupt sources // IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF); IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF); return EFI_SUCCESS; }
/** Get next token space in PCD database according to given token space guid. @param Guid Given token space guid. If NULL, then Guid will be set to the first PCD token space in PCD database, If not NULL, then Guid will be set to next PCD token space. @retval EFI_UNSUPPORTED @retval EFI_NOT_FOUND If PCD database has no token space table or can not find given token space in PCD database. @retval EFI_SUCCESS Success to get next token space guid. **/ EFI_STATUS EFIAPI DxePcdGetNextTokenSpace ( IN OUT CONST EFI_GUID **Guid ) { UINTN Idx; UINTN Idx2; UINTN Idx3; UINTN PeiTokenSpaceTableSize; UINTN DxeTokenSpaceTableSize; EFI_GUID **PeiTokenSpaceTable; EFI_GUID **DxeTokenSpaceTable; BOOLEAN Match; BOOLEAN PeiExMapTableEmpty; BOOLEAN DxeExMapTableEmpty; ASSERT (Guid != NULL); PeiExMapTableEmpty = PEI_EXMAP_TABLE_EMPTY; DxeExMapTableEmpty = DXE_EXMAP_TABLE_EMPTY; if (PeiExMapTableEmpty && DxeExMapTableEmpty) { if (*Guid != NULL) { return EFI_NOT_FOUND; } else { return EFI_SUCCESS; } } if (TmpTokenSpaceBuffer[0] == NULL) { PeiTokenSpaceTableSize = 0; if (!PeiExMapTableEmpty) { PeiTokenSpaceTableSize = PEI_EXMAPPING_TABLE_SIZE; PeiTokenSpaceTable = GetDistinctTokenSpace (&PeiTokenSpaceTableSize, mPcdDatabase->PeiDb.Init.ExMapTable, mPcdDatabase->PeiDb.Init.GuidTable ); CopyMem (TmpTokenSpaceBuffer, PeiTokenSpaceTable, sizeof (EFI_GUID*) * PeiTokenSpaceTableSize); } if (!DxeExMapTableEmpty) { DxeTokenSpaceTableSize = DXE_EXMAPPING_TABLE_SIZE; DxeTokenSpaceTable = GetDistinctTokenSpace (&DxeTokenSpaceTableSize, mPcdDatabase->DxeDb.Init.ExMapTable, mPcdDatabase->DxeDb.Init.GuidTable ); // // Make sure EFI_GUID in DxeTokenSpaceTable does not exist in PeiTokenSpaceTable // for (Idx2 = 0, Idx3 = PeiTokenSpaceTableSize; Idx2 < DxeTokenSpaceTableSize; Idx2++) { Match = FALSE; for (Idx = 0; Idx < PeiTokenSpaceTableSize; Idx++) { if (CompareGuid (TmpTokenSpaceBuffer[Idx], DxeTokenSpaceTable[Idx2])) { Match = TRUE; break; } } if (!Match) { TmpTokenSpaceBuffer[Idx3++] = DxeTokenSpaceTable[Idx2]; } } } } if (*Guid == NULL) { *Guid = TmpTokenSpaceBuffer[0]; return EFI_SUCCESS; } for (Idx = 0; Idx < (PEI_EXMAPPING_TABLE_SIZE + DXE_EXMAPPING_TABLE_SIZE); Idx++) { if(CompareGuid (*Guid, TmpTokenSpaceBuffer[Idx])) { Idx++; *Guid = TmpTokenSpaceBuffer[Idx]; return EFI_SUCCESS; } } return EFI_NOT_FOUND; }
/** Restore Partition Table to its alternate place (Primary -> Backup or Backup -> Primary). @param[in] BlockIo Parent BlockIo interface. @param[in] DiskIo Disk Io Protocol. @param[in] PartHeader Partition table header structure. @retval TRUE Restoring succeeds @retval FALSE Restoring failed **/ BOOLEAN PartitionRestoreGptTable ( IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_PARTITION_TABLE_HEADER *PartHeader ) { EFI_STATUS Status; UINTN BlockSize; EFI_PARTITION_TABLE_HEADER *PartHdr; EFI_LBA PEntryLBA; UINT8 *Ptr; UINT32 MediaId; PartHdr = NULL; Ptr = NULL; BlockSize = BlockIo->Media->BlockSize; MediaId = BlockIo->Media->MediaId; PartHdr = AllocateZeroPool (BlockSize); if (PartHdr == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); return FALSE; } PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \ (PartHeader->LastUsableLBA + 1) : \ (PRIMARY_PART_HEADER_LBA + 1); CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER)); PartHdr->MyLBA = PartHeader->AlternateLBA; PartHdr->AlternateLBA = PartHeader->MyLBA; PartHdr->PartitionEntryLBA = PEntryLBA; PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr); Status = DiskIo->WriteDisk ( DiskIo, MediaId, MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize), BlockSize, PartHdr ); if (EFI_ERROR (Status)) { goto Done; } Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); if (Ptr == NULL) { DEBUG ((EFI_D_ERROR, " Allocate pool error\n")); Status = EFI_OUT_OF_RESOURCES; goto Done; } Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize), PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, Ptr ); if (EFI_ERROR (Status)) { goto Done; } Status = DiskIo->WriteDisk ( DiskIo, MediaId, MultU64x32(PEntryLBA, (UINT32) BlockSize), PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, Ptr ); Done: FreePool (PartHdr); if (Ptr != NULL) { FreePool (Ptr); } if (EFI_ERROR (Status)) { return FALSE; } return TRUE; }
/** Install child handles if the Handle supports GPT partition structure. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path. @retval EFI_SUCCESS Valid GPT disk. @retval EFI_MEDIA_CHANGED Media changed Detected. @retval other Not a valid GPT disk. **/ EFI_STATUS PartitionInstallGptChildHandles ( 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; UINT32 BlockSize; EFI_LBA LastBlock; MASTER_BOOT_RECORD *ProtectiveMbr; EFI_PARTITION_TABLE_HEADER *PrimaryHeader; EFI_PARTITION_TABLE_HEADER *BackupHeader; EFI_PARTITION_ENTRY *PartEntry; EFI_PARTITION_ENTRY *Entry; EFI_PARTITION_ENTRY_STATUS *PEntryStatus; UINTN Index; EFI_STATUS GptValidStatus; HARDDRIVE_DEVICE_PATH HdDev; UINT32 MediaId; LogFlowFuncMarkDP(DevicePath); ProtectiveMbr = NULL; PrimaryHeader = NULL; BackupHeader = NULL; PartEntry = NULL; PEntryStatus = NULL; BlockSize = BlockIo->Media->BlockSize; LastBlock = BlockIo->Media->LastBlock; MediaId = BlockIo->Media->MediaId; DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize)); DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock)); GptValidStatus = EFI_NOT_FOUND; // // Allocate a buffer for the Protective MBR // ProtectiveMbr = AllocatePool (BlockSize); if (ProtectiveMbr == NULL) { return EFI_NOT_FOUND; } // // Read the Protective MBR from LBA #0 // Status = DiskIo->ReadDisk ( DiskIo, MediaId, 0, BlockSize, ProtectiveMbr ); if (EFI_ERROR (Status)) { GptValidStatus = Status; goto Done; } // // Verify that the Protective MBR is valid // for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { if (ProtectiveMbr->Partition[Index].BootIndicator == 0x00 && ProtectiveMbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION && UNPACK_UINT32 (ProtectiveMbr->Partition[Index].StartingLBA) == 1 ) { break; } } if (Index == MAX_MBR_PARTITIONS) { goto Done; } // // Allocate the GPT structures // PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); if (PrimaryHeader == NULL) { goto Done; } BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); if (BackupHeader == NULL) { goto Done; } // // Check primary and backup partition tables // if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n")); if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) { DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n")); goto Done; } else { DEBUG ((EFI_D_INFO, " Valid backup partition table\n")); DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n")); if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) { DEBUG ((EFI_D_INFO, " Restore primary partition table error\n")); } if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); } } } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n")); DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n")); if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table error\n")); } if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); } } DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n")); // // Read the EFI Partition Entries // PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); if (PartEntry == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); goto Done; } Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize), PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry), PartEntry ); if (EFI_ERROR (Status)) { GptValidStatus = Status; DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk error\n")); goto Done; } DEBUG ((EFI_D_INFO, " Partition entries read block success\n")); DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries)); PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS)); if (PEntryStatus == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); goto Done; } // // Check the integrity of partition entries // PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus); // // If we got this far the GPT layout of the disk is valid and we should return true // GptValidStatus = EFI_SUCCESS; // // Create child device handles // for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index * PrimaryHeader->SizeOfPartitionEntry); if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid) || PEntryStatus[Index].OutOfRange || PEntryStatus[Index].Overlap || PEntryStatus[Index].OsSpecific ) { // // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific // partition Entries // continue; } ZeroMem (&HdDev, sizeof (HdDev)); HdDev.Header.Type = MEDIA_DEVICE_PATH; HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); HdDev.PartitionNumber = (UINT32) Index + 1; HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; HdDev.SignatureType = SIGNATURE_TYPE_GUID; HdDev.PartitionStart = Entry->StartingLBA; HdDev.PartitionSize = Entry->EndingLBA - Entry->StartingLBA + 1; CopyMem (HdDev.Signature, &Entry->UniquePartitionGUID, sizeof (EFI_GUID)); DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index)); DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart)); DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) Entry->EndingLBA)); DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize)); DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (Entry->StartingLBA, BlockSize))); DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (Entry->EndingLBA, BlockSize))); Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, Entry->StartingLBA, Entry->EndingLBA, BlockSize, CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid) ); } DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n")); Done: if (ProtectiveMbr != NULL) { FreePool (ProtectiveMbr); } if (PrimaryHeader != NULL) { FreePool (PrimaryHeader); } if (BackupHeader != NULL) { FreePool (BackupHeader); } if (PartEntry != NULL) { FreePool (PartEntry); } if (PEntryStatus != NULL) { FreePool (PEntryStatus); } return GptValidStatus; }
EFI_STATUS EFIAPI WinNtSerialIoSetAttributes ( IN EFI_SERIAL_IO_PROTOCOL *This, IN UINT64 BaudRate, IN UINT32 ReceiveFifoDepth, IN UINT32 Timeout, IN EFI_PARITY_TYPE Parity, IN UINT8 DataBits, IN EFI_STOP_BITS_TYPE StopBits ) /*++ Routine Description: This function is used to set the attributes. Arguments: This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue. BaudRate - The Baud rate of the serial device. ReceiveFifoDepth - The request depth of fifo on receive side. Timeout - the request timeout for a single charact. Parity - The type of parity used in serial device. DataBits - Number of deata bits used in serial device. StopBits - Number of stop bits used in serial device. Returns: Status code None --*/ // TODO: EFI_SUCCESS - add return value to function comment // TODO: EFI_DEVICE_ERROR - add return value to function comment // TODO: EFI_DEVICE_ERROR - add return value to function comment // TODO: EFI_DEVICE_ERROR - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment // TODO: EFI_DEVICE_ERROR - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; UINTN Index; WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; COMMTIMEOUTS PortTimeOuts; DWORD ConvertedTime; BOOL Result; UART_DEVICE_PATH *Uart; EFI_TPL Tpl; Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); // // Some of our arguments have defaults if a null value is passed in, and // we must set the default values if a null argument is passed in. // if (BaudRate == 0) { BaudRate = PcdGet64 (PcdUartDefaultBaudRate); } if (ReceiveFifoDepth == 0) { ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; } if (Timeout == 0) { Timeout = SERIAL_TIMEOUT_DEFAULT; } if (Parity == DefaultParity) { Parity = (EFI_PARITY_TYPE) (PcdGet8 (PcdUartDefaultParity)); } if (DataBits == 0) { DataBits = PcdGet8 (PcdUartDefaultDataBits); } if (StopBits == DefaultStopBits) { StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits); } // // Make sure all parameters are valid // if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) { return EFI_INVALID_PARAMETER; } // //The lower baud rate supported by the serial device will be selected without exceeding the unsupported BaudRate parameter // for (Index = 1; Index < (ARRAY_SIZE (mBaudRateCurrentSupport)); Index++) { if (BaudRate < mBaudRateCurrentSupport[Index]) { BaudRate = mBaudRateCurrentSupport[Index-1]; break; } } if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) { return EFI_INVALID_PARAMETER; } if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) { return EFI_INVALID_PARAMETER; } if ((Parity < NoParity) || (Parity > SpaceParity)) { return EFI_INVALID_PARAMETER; } if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) { return EFI_INVALID_PARAMETER; } // // Now we only support DataBits=7,8. // if ((DataBits < 7) || (DataBits > 8)) { return EFI_INVALID_PARAMETER; } // // Now we only support DataBits=7,8. // for DataBits = 6,7,8, StopBits can not set OneFiveStopBits. // if (StopBits == OneFiveStopBits) { return EFI_INVALID_PARAMETER; } // // See if the new attributes already match the current attributes // if (Private->UartDevicePath.BaudRate == BaudRate && Private->UartDevicePath.DataBits == DataBits && Private->UartDevicePath.Parity == Parity && Private->UartDevicePath.StopBits == StopBits && Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth && Private->SerialIoMode.Timeout == Timeout ) { return EFI_SUCCESS; } Tpl = gBS->RaiseTPL (TPL_NOTIFY); // // Get current values from NT // ZeroMem (&Private->NtDCB, sizeof (DCB)); Private->NtDCB.DCBlength = sizeof (DCB); if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) { Private->NtError = Private->WinNtThunk->GetLastError (); DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError)); gBS->RestoreTPL (Tpl); return EFI_DEVICE_ERROR; } // // Map EFI com setting to NT // Private->NtDCB.BaudRate = ConvertBaud2Nt (BaudRate); Private->NtDCB.ByteSize = ConvertData2Nt (DataBits); Private->NtDCB.Parity = ConvertParity2Nt (Parity); Private->NtDCB.StopBits = ConvertStop2Nt (StopBits); Private->NtDCB.fBinary = TRUE; Private->NtDCB.fParity = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE; Private->NtDCB.fOutxCtsFlow = FALSE; Private->NtDCB.fOutxDsrFlow = FALSE; Private->NtDCB.fDtrControl = DTR_CONTROL_ENABLE; Private->NtDCB.fDsrSensitivity = FALSE; Private->NtDCB.fOutX = FALSE; Private->NtDCB.fInX = FALSE; Private->NtDCB.fRtsControl = RTS_CONTROL_ENABLE; Private->NtDCB.fNull = FALSE; // // Set new values // Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB); if (!Result) { Private->NtError = Private->WinNtThunk->GetLastError (); DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError)); gBS->RestoreTPL (Tpl); return EFI_DEVICE_ERROR; } // // Set com port read/write timeout values // ConvertedTime = ConvertTime2Nt (Timeout); PortTimeOuts.ReadIntervalTimeout = MAXDWORD; PortTimeOuts.ReadTotalTimeoutMultiplier = 0; PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime; PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime; PortTimeOuts.WriteTotalTimeoutConstant = 0; if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) { Private->NtError = Private->WinNtThunk->GetLastError (); DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError)); gBS->RestoreTPL (Tpl); return EFI_DEVICE_ERROR; } // // Update mode // Private->SerialIoMode.BaudRate = BaudRate; Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth; Private->SerialIoMode.Timeout = Timeout; Private->SerialIoMode.Parity = Parity; Private->SerialIoMode.DataBits = DataBits; Private->SerialIoMode.StopBits = StopBits; // // See if Device Path Node has actually changed // if (Private->UartDevicePath.BaudRate == BaudRate && Private->UartDevicePath.DataBits == DataBits && Private->UartDevicePath.Parity == Parity && Private->UartDevicePath.StopBits == StopBits ) { gBS->RestoreTPL(Tpl); return EFI_SUCCESS; } // // Update the device path // Private->UartDevicePath.BaudRate = BaudRate; Private->UartDevicePath.DataBits = DataBits; Private->UartDevicePath.Parity = (UINT8) Parity; Private->UartDevicePath.StopBits = (UINT8) StopBits; Status = EFI_SUCCESS; if (Private->Handle != NULL) { Uart = (UART_DEVICE_PATH *) ( (UINTN) Private->DevicePath + GetDevicePathSize (Private->ParentDevicePath) - END_DEVICE_PATH_LENGTH ); CopyMem (Uart, &Private->UartDevicePath, sizeof (UART_DEVICE_PATH)); Status = gBS->ReinstallProtocolInterface ( Private->Handle, &gEfiDevicePathProtocolGuid, Private->DevicePath, Private->DevicePath ); } gBS->RestoreTPL (Tpl); return Status; }
/** Get and dump SMRAM profile data. @return EFI_SUCCESS Get the SMRAM profile data successfully. @return other Fail to get the SMRAM profile data. **/ EFI_STATUS GetSmramProfileData ( VOID ) { EFI_STATUS Status; UINTN CommSize; UINT8 *CommBuffer; EFI_SMM_COMMUNICATE_HEADER *CommHeader; SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *CommGetProfileInfo; SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *CommGetProfileData; UINT64 ProfileSize; PHYSICAL_ADDRESS ProfileBuffer; EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SmramProfile: Locate SmmCommunication protocol - %r\n", Status)); return Status; } CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA); CommBuffer = AllocateZeroPool (CommSize); if (CommBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; Print (L"SmramProfile: AllocateZeroPool (0x%x) for comm buffer - %r\n", CommSize, Status); return Status; } // // Get Size // CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof (gEdkiiMemoryProfileGuid)); CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO); CommGetProfileInfo = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_INFO *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetProfileInfo->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_INFO; CommGetProfileInfo->Header.DataLength = sizeof (*CommGetProfileInfo); CommGetProfileInfo->Header.ReturnStatus = (UINT64)-1; CommGetProfileInfo->ProfileSize = 0; CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); if (EFI_ERROR (Status)) { FreePool (CommBuffer); DEBUG ((EFI_D_ERROR, "SmramProfile: SmmCommunication - %r\n", Status)); return Status; } if (CommGetProfileInfo->Header.ReturnStatus != 0) { Print (L"SmramProfile: GetProfileInfo - 0x%0x\n", CommGetProfileInfo->Header.ReturnStatus); return EFI_SUCCESS; } ProfileSize = CommGetProfileInfo->ProfileSize; // // Get Data // ProfileBuffer = (PHYSICAL_ADDRESS) (UINTN) AllocateZeroPool ((UINTN) ProfileSize); if (ProfileBuffer == 0) { FreePool (CommBuffer); Status = EFI_OUT_OF_RESOURCES; Print (L"SmramProfile: AllocateZeroPool (0x%x) for profile buffer - %r\n", (UINTN) ProfileSize, Status); return Status; } CommHeader = (EFI_SMM_COMMUNICATE_HEADER *) &CommBuffer[0]; CopyMem (&CommHeader->HeaderGuid, &gEdkiiMemoryProfileGuid, sizeof(gEdkiiMemoryProfileGuid)); CommHeader->MessageLength = sizeof (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA); CommGetProfileData = (SMRAM_PROFILE_PARAMETER_GET_PROFILE_DATA *) &CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetProfileData->Header.Command = SMRAM_PROFILE_COMMAND_GET_PROFILE_DATA; CommGetProfileData->Header.DataLength = sizeof (*CommGetProfileData); CommGetProfileData->Header.ReturnStatus = (UINT64)-1; CommGetProfileData->ProfileSize = ProfileSize; CommGetProfileData->ProfileBuffer = ProfileBuffer; CommSize = sizeof (EFI_GUID) + sizeof (UINTN) + CommHeader->MessageLength; Status = SmmCommunication->Communicate (SmmCommunication, CommBuffer, &CommSize); ASSERT_EFI_ERROR (Status); if (CommGetProfileData->Header.ReturnStatus != 0) { FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer); FreePool (CommBuffer); Print (L"GetProfileData - 0x%x\n", CommGetProfileData->Header.ReturnStatus); return EFI_SUCCESS; } Print (L"SmramProfileSize - 0x%x\n", CommGetProfileData->ProfileSize); Print (L"======= SmramProfile begin =======\n"); DumpMemoryProfile (CommGetProfileData->ProfileBuffer, CommGetProfileData->ProfileSize); Print (L"======= SmramProfile end =======\n\n\n"); FreePool ((VOID *) (UINTN) CommGetProfileData->ProfileBuffer); FreePool (CommBuffer); return EFI_SUCCESS; }
/** Used to allocate and build a device path node for a SCSI device on a SCSI channel. @param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. @param[in] Target The Target is an array of size TARGET_MAX_BYTES and it specifies the Target ID of the SCSI device for which a device path node is to be allocated and built. Transport drivers may chose to utilize a subset of this size to suit the representation of targets. For example, a Fibre Channel driver may use only 8 bytes (WWN) in the array to represent a FC target. @param[in] Lun The LUN of the SCSI device for which a device path node is to be allocated and built. @param[in, out] DevicePath A pointer to a single device path node that describes the SCSI device specified by Target and Lun. This function is responsible for allocating the buffer DevicePath with the boot service AllocatePool(). It is the caller's responsibility to free DevicePath when the caller is finished with DevicePath. @retval EFI_SUCCESS The device path node that describes the SCSI device specified by Target and Lun was allocated and returned in DevicePath. @retval EFI_INVALID_PARAMETER DevicePath is NULL. @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does not exist on the SCSI channel. @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath. **/ EFI_STATUS EFIAPI IScsiExtScsiPassThruBuildDevicePath ( IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN UINT8 *Target, IN UINT64 Lun, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath ) { ISCSI_DRIVER_DATA *Private; ISCSI_SESSION *Session; ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData; ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig; EFI_DEV_PATH *Node; UINTN DevPathNodeLen; if (DevicePath == NULL) { return EFI_INVALID_PARAMETER; } if (Target[0] != 0) { return EFI_NOT_FOUND; } Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This); Session = &Private->Session; ConfigNvData = &Session->ConfigData.NvData; AuthConfig = &Session->AuthData.AuthConfig; if (CompareMem (&Lun, ConfigNvData->BootLun, sizeof (UINT64)) != 0) { return EFI_NOT_FOUND; } DevPathNodeLen = sizeof (ISCSI_DEVICE_PATH) + AsciiStrLen (ConfigNvData->TargetName) + 1; Node = AllocatePool (DevPathNodeLen); if (Node == NULL) { return EFI_OUT_OF_RESOURCES; } Node->DevPath.Type = MESSAGING_DEVICE_PATH; Node->DevPath.SubType = MSG_ISCSI_DP; SetDevicePathNodeLength (&Node->DevPath, (UINT16)DevPathNodeLen); // // 0 for TCP, others are reserved. // Node->Iscsi.NetworkProtocol = 0; Node->Iscsi.LoginOption = 0; switch (AuthConfig->CHAPType) { case ISCSI_CHAP_NONE: Node->Iscsi.LoginOption |= 0x0800; break; case ISCSI_CHAP_UNI: Node->Iscsi.LoginOption |= 0x1000; break; default: break; } CopyMem (&Node->Iscsi.Lun, ConfigNvData->BootLun, sizeof (UINT64)); Node->Iscsi.TargetPortalGroupTag = Session->TargetPortalGroupTag; AsciiStrCpy ((CHAR8 *) Node + sizeof (ISCSI_DEVICE_PATH), ConfigNvData->TargetName); *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; return EFI_SUCCESS; }
/** Create PRP lists for Data transfer which is larger than 2 memory pages. @param[in] Private The pointer to the PEI_NVME_CONTROLLER_PRIVATE_DATA data structure. @param[in] PhysicalAddr The physical base address of Data Buffer. @param[in] Pages The number of pages to be transfered. @retval The pointer Value to the first PRP List of the PRP lists. **/ UINT64 NvmeCreatePrpList ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private, IN EFI_PHYSICAL_ADDRESS PhysicalAddr, IN UINTN Pages ) { UINTN PrpEntryNo; UINTN PrpListNo; UINT64 PrpListBase; VOID *PrpListHost; UINTN PrpListIndex; UINTN PrpEntryIndex; UINT64 Remainder; EFI_PHYSICAL_ADDRESS PrpListPhyAddr; UINTN Bytes; UINT8 *PrpEntry; EFI_PHYSICAL_ADDRESS NewPhyAddr; // // 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, &Remainder); if (Remainder != 0) { PrpListNo += 1; } if (PrpListNo > NVME_PRP_SIZE) { DEBUG (( DEBUG_ERROR, "%a: The implementation only supports PrpList number up to 4." " But %d are needed here.\n", __FUNCTION__, PrpListNo )); return 0; } PrpListHost = (VOID *)(UINTN) NVME_PRP_BASE (Private); Bytes = EFI_PAGES_TO_SIZE (PrpListNo); PrpListPhyAddr = (UINT64)(UINTN)(PrpListHost); // // Fill all PRP lists except of last one. // ZeroMem (PrpListHost, Bytes); for (PrpListIndex = 0; PrpListIndex < PrpListNo - 1; ++PrpListIndex) { PrpListBase = (UINTN)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) { PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64)); if (PrpEntryIndex != PrpEntryNo - 1) { // // Fill all PRP entries except of last one. // CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64)); PhysicalAddr += EFI_PAGE_SIZE; } else { // // Fill last PRP entries with next PRP List pointer. // NewPhyAddr = (PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE); CopyMem (PrpEntry, (VOID *)(UINTN) (&NewPhyAddr), sizeof (UINT64)); } } } // // Fill last PRP list. // PrpListBase = (UINTN)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder : PrpEntryNo); ++PrpEntryIndex) { PrpEntry = (UINT8 *)(UINTN) (PrpListBase + PrpEntryIndex * sizeof(UINT64)); CopyMem (PrpEntry, (VOID *)(UINTN) (&PhysicalAddr), sizeof (UINT64)); PhysicalAddr += EFI_PAGE_SIZE; } return PrpListPhyAddr; }
/** This command is used to read the public area and Name of an NV Index. @param[in] NvIndex The NV Index. @param[out] NvPublic The public area of the index. @param[out] NvName The Name of the nvIndex. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. **/ EFI_STATUS EFIAPI Tpm2NvReadPublic ( IN TPMI_RH_NV_INDEX NvIndex, OUT TPM2B_NV_PUBLIC *NvPublic, OUT TPM2B_NAME *NvName ) { EFI_STATUS Status; TPM2_NV_READPUBLIC_COMMAND SendBuffer; TPM2_NV_READPUBLIC_RESPONSE RecvBuffer; UINT32 SendBufferSize; UINT32 RecvBufferSize; UINT16 NvPublicSize; UINT16 NvNameSize; UINT8 *Buffer; TPM_RC ResponseCode; // // Construct command // SendBuffer.Header.tag = SwapBytes16(TPM_ST_NO_SESSIONS); SendBuffer.Header.commandCode = SwapBytes32(TPM_CC_NV_ReadPublic); SendBuffer.NvIndex = SwapBytes32 (NvIndex); SendBufferSize = (UINT32) sizeof (SendBuffer); SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); // // send Tpm command // RecvBufferSize = sizeof (RecvBuffer); Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); if (EFI_ERROR (Status)) { return Status; } if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_DEVICE_ERROR; } ResponseCode = SwapBytes32(RecvBuffer.Header.responseCode); if (ResponseCode != TPM_RC_SUCCESS) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - responseCode - %x\n", SwapBytes32(RecvBuffer.Header.responseCode))); } switch (ResponseCode) { case TPM_RC_SUCCESS: // return data break; case TPM_RC_HANDLE + RC_NV_ReadPublic_nvIndex: // TPM_RC_NV_DEFINED: return EFI_NOT_FOUND; case TPM_RC_VALUE + RC_NV_ReadPublic_nvIndex: return EFI_INVALID_PARAMETER; default: return EFI_DEVICE_ERROR; } if (RecvBufferSize <= sizeof (TPM2_RESPONSE_HEADER) + sizeof (UINT16) + sizeof(UINT16)) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - %x\n", RecvBufferSize)); return EFI_NOT_FOUND; } // // Basic check // NvPublicSize = SwapBytes16 (RecvBuffer.NvPublic.size); NvNameSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)((UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize))); if (RecvBufferSize != sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize + sizeof(UINT16) + NvNameSize) { DEBUG ((EFI_D_ERROR, "Tpm2NvReadPublic - RecvBufferSize Error - NvPublicSize %x, NvNameSize %x\n", RecvBufferSize, NvNameSize)); return EFI_NOT_FOUND; } // // Return the response // CopyMem (NvPublic, &RecvBuffer.NvPublic, sizeof(UINT16) + NvPublicSize); NvPublic->size = NvPublicSize; NvPublic->nvPublic.nvIndex = SwapBytes32 (NvPublic->nvPublic.nvIndex); NvPublic->nvPublic.nameAlg = SwapBytes16 (NvPublic->nvPublic.nameAlg); WriteUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes, SwapBytes32 (ReadUnaligned32 ((UINT32 *)&NvPublic->nvPublic.attributes))); NvPublic->nvPublic.authPolicy.size = SwapBytes16 (NvPublic->nvPublic.authPolicy.size); Buffer = (UINT8 *)&NvPublic->nvPublic.authPolicy; Buffer += sizeof(UINT16) + NvPublic->nvPublic.authPolicy.size; NvPublic->nvPublic.dataSize = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer)); CopyMem (NvName, (UINT8 *)&RecvBuffer + sizeof(TPM2_RESPONSE_HEADER) + sizeof(UINT16) + NvPublicSize, NvNameSize); NvName->size = NvNameSize; return EFI_SUCCESS; }
/** Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function only supports blocking execution of the command. @param[in] Private The pointer to the NVME_CONTEXT Data structure. @param[in] NamespaceId Is a 32 bit Namespace ID to which the Express HCI command packet will be sent. A Value of 0 denotes the NVM Express controller, a Value of all 0FFh in the namespace ID specifies that the command packet should be sent to all valid namespaces. @param[in,out] Packet A pointer to the EDKII PEI NVM Express PassThru Command Packet to send to the NVMe namespace specified by NamespaceId. @retval EFI_SUCCESS The EDKII PEI NVM Express Command Packet was sent by the host. TransferLength bytes were transferred to, or from DataBuffer. @retval EFI_NOT_READY The EDKII PEI NVM Express Command Packet could not be sent because the controller is not ready. The caller may retry again later. @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the EDKII PEI NVM Express Command Packet. @retval EFI_INVALID_PARAMETER Namespace, or the contents of EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The EDKII PEI NVM Express Command Packet was not sent, so no additional status information is available. @retval EFI_UNSUPPORTED The command described by the EDKII PEI NVM Express Command Packet is not supported by the host adapter. The EDKII PEI NVM Express Command Packet was not sent, so no additional status information is available. @retval EFI_TIMEOUT A timeout occurred while waiting for the EDKII PEI NVM Express Command Packet to execute. **/ EFI_STATUS NvmePassThru ( IN PEI_NVME_CONTROLLER_PRIVATE_DATA *Private, IN UINT32 NamespaceId, IN OUT EDKII_PEI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet ) { EFI_STATUS Status; NVME_SQ *Sq; NVME_CQ *Cq; UINT8 QueueId; UINTN SqSize; UINTN CqSize; EDKII_IOMMU_OPERATION MapOp; UINTN MapLength; EFI_PHYSICAL_ADDRESS PhyAddr; VOID *MapData; VOID *MapMeta; UINT32 Bytes; UINT32 Offset; UINT32 Data32; UINT64 Timer; // // Check the data fields in Packet parameter // if (Packet == NULL) { DEBUG (( DEBUG_ERROR, "%a, Invalid parameter: Packet(%lx)\n", __FUNCTION__, (UINTN)Packet )); return EFI_INVALID_PARAMETER; } if ((Packet->NvmeCmd == NULL) || (Packet->NvmeCompletion == NULL)) { DEBUG (( DEBUG_ERROR, "%a, Invalid parameter: NvmeCmd (%lx)/NvmeCompletion(%lx)\n", __FUNCTION__, (UINTN)Packet->NvmeCmd, (UINTN)Packet->NvmeCompletion )); return EFI_INVALID_PARAMETER; } if (Packet->QueueType != NVME_ADMIN_QUEUE && Packet->QueueType != NVME_IO_QUEUE) { DEBUG (( DEBUG_ERROR, "%a, Invalid parameter: QueueId(%lx)\n", __FUNCTION__, (UINTN)Packet->QueueType )); return EFI_INVALID_PARAMETER; } QueueId = Packet->QueueType; Sq = Private->SqBuffer[QueueId] + Private->SqTdbl[QueueId].Sqt; Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; if (QueueId == NVME_ADMIN_QUEUE) { SqSize = NVME_ASQ_SIZE + 1; CqSize = NVME_ACQ_SIZE + 1; } else { SqSize = NVME_CSQ_SIZE + 1; CqSize = NVME_CCQ_SIZE + 1; } if (Packet->NvmeCmd->Nsid != NamespaceId) { DEBUG (( DEBUG_ERROR, "%a: Nsid mismatch (%x, %x)\n", __FUNCTION__, Packet->NvmeCmd->Nsid, NamespaceId )); return EFI_INVALID_PARAMETER; } ZeroMem (Sq, sizeof (NVME_SQ)); Sq->Opc = Packet->NvmeCmd->Cdw0.Opcode; Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation; Sq->Cid = Packet->NvmeCmd->Cdw0.Cid; Sq->Nsid = Packet->NvmeCmd->Nsid; // // Currently we only support PRP for data transfer, SGL is NOT supported // ASSERT (Sq->Psdt == 0); if (Sq->Psdt != 0) { DEBUG ((DEBUG_ERROR, "%a: Does not support SGL mechanism.\n", __FUNCTION__)); return EFI_UNSUPPORTED; } Sq->Prp[0] = (UINT64)(UINTN)Packet->TransferBuffer; Sq->Prp[1] = 0; MapData = NULL; MapMeta = NULL; Status = EFI_SUCCESS; // // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller // specific addresses. // if ((Sq->Opc & (BIT0 | BIT1)) != 0) { if (((Packet->TransferLength != 0) && (Packet->TransferBuffer == NULL)) || ((Packet->TransferLength == 0) && (Packet->TransferBuffer != NULL))) { return EFI_INVALID_PARAMETER; } // // Currently, we only support creating IO submission/completion queues that are // allocated internally by the driver. // if ((Packet->QueueType == NVME_ADMIN_QUEUE) && ((Sq->Opc == NVME_ADMIN_CRIOCQ_CMD) || (Sq->Opc == NVME_ADMIN_CRIOSQ_CMD))) { if ((Packet->TransferBuffer != Private->SqBuffer[NVME_IO_QUEUE]) && (Packet->TransferBuffer != Private->CqBuffer[NVME_IO_QUEUE])) { DEBUG (( DEBUG_ERROR, "%a: Does not support external IO queues creation request.\n", __FUNCTION__ )); return EFI_UNSUPPORTED; } } else { if ((Sq->Opc & BIT0) != 0) { MapOp = EdkiiIoMmuOperationBusMasterRead; } else { MapOp = EdkiiIoMmuOperationBusMasterWrite; } if ((Packet->TransferLength != 0) && (Packet->TransferBuffer != NULL)) { MapLength = Packet->TransferLength; Status = IoMmuMap ( MapOp, Packet->TransferBuffer, &MapLength, &PhyAddr, &MapData ); if (EFI_ERROR (Status) || (MapLength != Packet->TransferLength)) { Status = EFI_OUT_OF_RESOURCES; DEBUG ((DEBUG_ERROR, "%a: Fail to map data buffer.\n", __FUNCTION__)); goto Exit; } Sq->Prp[0] = PhyAddr; } if((Packet->MetadataLength != 0) && (Packet->MetadataBuffer != NULL)) { MapLength = Packet->MetadataLength; Status = IoMmuMap ( MapOp, Packet->MetadataBuffer, &MapLength, &PhyAddr, &MapMeta ); if (EFI_ERROR (Status) || (MapLength != Packet->MetadataLength)) { Status = EFI_OUT_OF_RESOURCES; DEBUG ((DEBUG_ERROR, "%a: Fail to map meta data buffer.\n", __FUNCTION__)); goto Exit; } Sq->Mptr = PhyAddr; } } } // // If the Buffer Size spans more than two memory pages (page Size as defined in CC.Mps), // then build a PRP list in the second PRP submission queue entry. // Offset = ((UINT32)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1); Bytes = Packet->TransferLength; if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) { // // Create PrpList for remaining Data Buffer. // PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); Sq->Prp[1] = NvmeCreatePrpList ( Private, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1 ); if (Sq->Prp[1] == 0) { Status = EFI_OUT_OF_RESOURCES; DEBUG ((DEBUG_ERROR, "%a: Create PRP list fail, Status - %r\n", __FUNCTION__, Status)); goto Exit; } } else if ((Offset + Bytes) > EFI_PAGE_SIZE) { Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); } if (Packet->NvmeCmd->Flags & CDW10_VALID) { Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10; } if (Packet->NvmeCmd->Flags & CDW11_VALID) { Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11; } if (Packet->NvmeCmd->Flags & CDW12_VALID) { Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12; } if (Packet->NvmeCmd->Flags & CDW13_VALID) { Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13; } if (Packet->NvmeCmd->Flags & CDW14_VALID) { Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14; } if (Packet->NvmeCmd->Flags & CDW15_VALID) { Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15; } // // Ring the submission queue doorbell. // Private->SqTdbl[QueueId].Sqt++; if (Private->SqTdbl[QueueId].Sqt == SqSize) { Private->SqTdbl[QueueId].Sqt = 0; } Data32 = ReadUnaligned32 ((UINT32 *)&Private->SqTdbl[QueueId]); Status = NVME_SET_SQTDBL (Private, QueueId, &Data32); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: NVME_SET_SQTDBL fail, Status - %r\n", __FUNCTION__, Status)); goto Exit; } // // Wait for completion queue to get filled in. // Status = EFI_TIMEOUT; Timer = 0; while (Timer < Packet->CommandTimeout) { if (Cq->Pt != Private->Pt[QueueId]) { Status = EFI_SUCCESS; break; } MicroSecondDelay (NVME_POLL_INTERVAL); Timer += NVME_POLL_INTERVAL; } if (Status == EFI_TIMEOUT) { // // Timeout occurs for an NVMe command, reset the controller to abort the outstanding command // DEBUG ((DEBUG_ERROR, "%a: Timeout occurs for the PassThru command.\n", __FUNCTION__)); Status = NvmeControllerInit (Private); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; } else { // // Return EFI_TIMEOUT to indicate a timeout occurs for PassThru command // Status = EFI_TIMEOUT; } goto Exit; } // // Move forward the Completion Queue head // Private->CqHdbl[QueueId].Cqh++; if (Private->CqHdbl[QueueId].Cqh == CqSize) { Private->CqHdbl[QueueId].Cqh = 0; Private->Pt[QueueId] ^= 1; } // // Copy the Respose Queue entry for this command to the callers response buffer // CopyMem (Packet->NvmeCompletion, Cq, sizeof (EDKII_PEI_NVM_EXPRESS_COMPLETION)); // // Check the NVMe cmd execution result // Status = NvmeCheckCqStatus (Cq); NVME_SET_CQHDBL (Private, QueueId, &Private->CqHdbl[QueueId]); Exit: if (MapMeta != NULL) { IoMmuUnmap (MapMeta); } if (MapData != NULL) { IoMmuUnmap (MapData); } return Status; }
/** Measure PE image into TPM log based on the authenticode image hashing in PE/COFF Specification 8.0 Appendix A. @param[in] TcgProtocol Pointer to the located TCG protocol instance. @param[in] ImageAddress Start address of image buffer. @param[in] ImageSize Image size @param[in] LinkTimeBase Address that the image is loaded into memory. @param[in] ImageType Image subsystem type. @param[in] FilePath File path is corresponding to the input image. @retval EFI_SUCCESS Successfully measure image. @retval EFI_OUT_OF_RESOURCES No enough resource to measure image. @retval other error value **/ EFI_STATUS EFIAPI TcgMeasurePeImage ( IN EFI_TCG_PROTOCOL *TcgProtocol, IN EFI_PHYSICAL_ADDRESS ImageAddress, IN UINTN ImageSize, IN UINTN LinkTimeBase, IN UINT16 ImageType, IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { EFI_STATUS Status; TCG_PCR_EVENT *TcgEvent; EFI_IMAGE_LOAD_EVENT *ImageLoad; UINT32 FilePathSize; VOID *Sha1Ctx; UINTN CtxSize; EFI_IMAGE_DOS_HEADER *DosHdr; UINT32 PeCoffHeaderOffset; EFI_IMAGE_SECTION_HEADER *Section; UINT8 *HashBase; UINTN HashSize; UINTN SumOfBytesHashed; EFI_IMAGE_SECTION_HEADER *SectionHeader; UINTN Index, Pos; UINT16 Magic; UINT32 EventSize; UINT32 EventNumber; EFI_PHYSICAL_ADDRESS EventLogLastEntry; EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; Status = EFI_SUCCESS; ImageLoad = NULL; SectionHeader = NULL; Sha1Ctx = NULL; FilePathSize = (UINT32) GetDevicePathSize (FilePath); // // Determine destination PCR by BootPolicy // EventSize = sizeof (*ImageLoad) - sizeof (ImageLoad->DevicePath) + FilePathSize; TcgEvent = AllocateZeroPool (EventSize + sizeof (TCG_PCR_EVENT)); if (TcgEvent == NULL) { return EFI_OUT_OF_RESOURCES; } TcgEvent->EventSize = EventSize; ImageLoad = (EFI_IMAGE_LOAD_EVENT *) TcgEvent->Event; switch (ImageType) { case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: TcgEvent->EventType = EV_EFI_BOOT_SERVICES_APPLICATION; TcgEvent->PCRIndex = 4; break; case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: TcgEvent->EventType = EV_EFI_BOOT_SERVICES_DRIVER; TcgEvent->PCRIndex = 2; break; case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: TcgEvent->EventType = EV_EFI_RUNTIME_SERVICES_DRIVER; TcgEvent->PCRIndex = 2; break; default: DEBUG (( EFI_D_ERROR, "TcgMeasurePeImage: Unknown subsystem type %d", ImageType )); Status = EFI_UNSUPPORTED; goto Finish; } ImageLoad->ImageLocationInMemory = ImageAddress; ImageLoad->ImageLengthInMemory = ImageSize; ImageLoad->ImageLinkTimeAddress = LinkTimeBase; ImageLoad->LengthOfDevicePath = FilePathSize; CopyMem (ImageLoad->DevicePath, FilePath, FilePathSize); // // Check PE/COFF image // DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress; PeCoffHeaderOffset = 0; if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { PeCoffHeaderOffset = DosHdr->e_lfanew; } if (((EFI_TE_IMAGE_HEADER *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset))->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { goto Finish; } // // PE/COFF Image Measurement // // NOTE: The following codes/steps are based upon the authenticode image hashing in // PE/COFF Specification 8.0 Appendix A. // // // 1. Load the image header into memory. // 2. Initialize a SHA hash context. CtxSize = Sha1GetContextSize (); Sha1Ctx = AllocatePool (CtxSize); if (Sha1Ctx == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Finish; } Sha1Init (Sha1Ctx); // // Measuring PE/COFF Image Header; // But CheckSum field and SECURITY data directory (certificate) are excluded // Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset); Magic = Hdr.Pe32->OptionalHeader.Magic; // // 3. Calculate the distance from the base of the image header to the image checksum address. // 4. Hash the image header from its base to beginning of the image checksum. // HashBase = (UINT8 *) (UINTN) ImageAddress; if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset // HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.CheckSum) - HashBase); } else { // // Use PE32+ offset // HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.CheckSum) - HashBase); } Sha1Update (Sha1Ctx, HashBase, HashSize); // // 5. Skip over the image checksum (it occupies a single ULONG). // 6. Get the address of the beginning of the Cert Directory. // 7. Hash everything from the end of the checksum to the start of the Cert Directory. // if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset // HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); } else { // // Use PE32+ offset // HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); HashSize = (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); } Sha1Update (Sha1Ctx, HashBase, HashSize); // // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) // 9. Hash everything from the end of the Cert Directory to the end of image header. // if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset // HashBase = (UINT8 *) &Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; HashSize = Hdr.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *)(&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress); } else { // // Use PE32+ offset // HashBase = (UINT8 *) &Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; HashSize = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *)(&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINT8 *) (UINTN) ImageAddress); } Sha1Update (Sha1Ctx, HashBase, HashSize); // // 10. Set the SUM_OF_BYTES_HASHED to the size of the header // if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset // SumOfBytesHashed = Hdr.Pe32->OptionalHeader.SizeOfHeaders; } else { // // Use PE32+ offset // SumOfBytesHashed = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders; } // // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER // structures in the image. The 'NumberOfSections' field of the image // header indicates how big the table should be. Do not include any // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero. // SectionHeader = (EFI_IMAGE_SECTION_HEADER *)AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * Hdr.Pe32->FileHeader.NumberOfSections); if (SectionHeader == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Finish; } // // 12. Using the 'PointerToRawData' in the referenced section headers as // a key, arrange the elements in the table in ascending order. In other // words, sort the section headers according to the disk-file offset of // the section. // Section = (EFI_IMAGE_SECTION_HEADER *) ( (UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER) + Hdr.Pe32->FileHeader.SizeOfOptionalHeader ); for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { Pos = Index; while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) { CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof(EFI_IMAGE_SECTION_HEADER)); Pos--; } CopyMem (&SectionHeader[Pos], Section, sizeof(EFI_IMAGE_SECTION_HEADER)); Section += 1; } // // 13. Walk through the sorted table, bring the corresponding section // into memory, and hash the entire section (using the 'SizeOfRawData' // field in the section header to determine the amount of data to hash). // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED . // 15. Repeat steps 13 and 14 for all the sections in the sorted table. // for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { Section = (EFI_IMAGE_SECTION_HEADER *) &SectionHeader[Index]; if (Section->SizeOfRawData == 0) { continue; } HashBase = (UINT8 *) (UINTN) ImageAddress + Section->PointerToRawData; HashSize = (UINTN) Section->SizeOfRawData; Sha1Update (Sha1Ctx, HashBase, HashSize); SumOfBytesHashed += HashSize; } // // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra // data in the file that needs to be added to the hash. This data begins // at file offset SUM_OF_BYTES_HASHED and its length is: // FileSize - (CertDirectory->Size) // if (ImageSize > SumOfBytesHashed) { HashBase = (UINT8 *) (UINTN) ImageAddress + SumOfBytesHashed; if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset // HashSize = (UINTN)(ImageSize - Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - SumOfBytesHashed); } else { // // Use PE32+ offset // HashSize = (UINTN)(ImageSize - Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - SumOfBytesHashed); } Sha1Update (Sha1Ctx, HashBase, HashSize); } // // 17. Finalize the SHA hash. // Sha1Final (Sha1Ctx, (UINT8 *)&TcgEvent->Digest); // // Log the PE data // EventNumber = 1; Status = TcgProtocol->HashLogExtendEvent ( TcgProtocol, (EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) NULL, 0, TPM_ALG_SHA, TcgEvent, &EventNumber, &EventLogLastEntry ); Finish: FreePool (TcgEvent); if (SectionHeader != NULL) { FreePool (SectionHeader); } if (Sha1Ctx != NULL ) { FreePool (Sha1Ctx); } return Status; }
EFI_STATUS CreateDMFontPkg(CHAR16* FontName, UINT16 FontWidth, UINT16 FontHeight, EFI_NARROW_GLYPH* NarrowGlyph, UINT32 NrSizeInBytes, CHAR16 NrStart, CHAR16 NrCharNum, EFI_WIDE_GLYPH* WideGlyph, UINT32 SizeInBytes, CHAR16 Start, CHAR16 CharNum) { EFI_HII_FONT_PACKAGE_HDR *FontPkgHeader; UINT32 PackageLength; UINT8 *Package; UINTN BlockLength = 0; UINT8 *pCurrent = 0; CHAR16 NextChar = 0; EFI_HII_GLYPH_INFO Cell = {FontWidth, FontHeight, 10, 10, (INT16)FontWidth}; UINT16 FontNameLen = StrLen(FontName); PackageLength = 4 + sizeof (EFI_HII_FONT_PACKAGE_HDR) + (FontNameLen*2 /*Max Length of Font Name*/) + sizeof(EFI_HII_GIBT_SKIP2_BLOCK) + sizeof(EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK) -1 + CharNum * WideGlyphBytes + sizeof(EFI_HII_GIBT_SKIP2_BLOCK) + sizeof(EFI_HII_GIBT_GLYPHS_BLOCK) -1 + NrCharNum * NrGlyphBytes + sizeof(EFI_GLYPH_GIBT_END_BLOCK) ; Package = (UINT8*)AllocateZeroPool (PackageLength); //ASSERT (Package != NULL); // Header WriteUnaligned32((UINT32 *) Package,PackageLength); FontPkgHeader = (EFI_HII_FONT_PACKAGE_HDR *) (Package + 4); FontPkgHeader->Header.Length = (UINT32) (PackageLength - 4); FontPkgHeader->Header.Type = EFI_HII_PACKAGE_FONTS; FontPkgHeader->HdrSize = sizeof(EFI_HII_FONT_PACKAGE_HDR) + (FontNameLen)*2; FontPkgHeader->GlyphBlockOffset = sizeof(EFI_HII_FONT_PACKAGE_HDR) + (FontNameLen*2); FontPkgHeader->Cell = Cell; FontPkgHeader->FontStyle = EFI_HII_FONT_STYLE_NORMAL; CopyMem((FontPkgHeader->FontFamily), FontName, StrLen(FontName)*2 +2); pCurrent = (UINT8 *) (Package + 4 + FontPkgHeader->GlyphBlockOffset); //CHAR 0...255 BlockLength = FillNarrowGLYPH(pCurrent, NarrowGlyph, NrSizeInBytes, 1, NrStart, NrCharNum); pCurrent += BlockLength; NextChar = NrStart + NrCharNum; // EFI_HII_GIBT_GLYPHS_DEFAULT BlockLength = FillWideGLYPH(pCurrent, WideGlyph, SizeInBytes, NextChar, Start, CharNum); pCurrent += BlockLength; // END BLOCK EFI_GLYPH_GIBT_END_BLOCK* FontEndBlock = (EFI_GLYPH_GIBT_END_BLOCK*)(pCurrent); FontEndBlock->Header.BlockType = (UINT8)EFI_HII_GIBT_END; // // Add this simplified font package to a package list then install it. // { EFI_HANDLE gFontHiiHandle = HiiAddPackages ( &gDMFontPackageListGuid , NULL, Package, NULL ); (void)gFontHiiHandle; //ASSERT (gFontHiiHandle != NULL); } FreePool (Package); return EFI_SUCCESS; }
/** Internal work function to fill in EFI_OPEN_FILE information for the Fs and BlkIo @param File Open file handle @param FileName Name of file after device stripped off **/ EFI_STATUS EblFileDevicePath ( IN OUT EFI_OPEN_FILE *File, IN CHAR8 *FileName, IN CONST UINT64 OpenMode ) { EFI_STATUS Status; UINTN Size; FILEPATH_DEVICE_PATH *FilePath; EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; CHAR16 UnicodeFileName[MAX_PATHNAME]; EFI_BLOCK_IO_PROTOCOL *BlkIo; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; EFI_FILE_HANDLE Root; if ( *FileName != 0 ) { AsciiStrToUnicodeStr (FileName, UnicodeFileName); } else { AsciiStrToUnicodeStr ("\\", UnicodeFileName); } Size = StrSize (UnicodeFileName); FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL)); if (FileDevicePath != NULL) { FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; FilePath->Header.Type = MEDIA_DEVICE_PATH; FilePath->Header.SubType = MEDIA_FILEPATH_DP; CopyMem (&FilePath->PathName, UnicodeFileName, Size); SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); if (File->EfiHandle != NULL) { File->DevicePath = DevicePathFromHandle (File->EfiHandle); } File->DevicePath = AppendDevicePath (File->DevicePath, FileDevicePath); FreePool (FileDevicePath); } Status = gBS->HandleProtocol (File->EfiHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo); if (!EFI_ERROR (Status)) { File->FsBlockIoMedia = BlkIo->Media; File->FsBlockIo = BlkIo; // If we are not opening the device this will get over written with file info File->MaxPosition = MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media->BlockSize); } if (File->Type == EfiOpenFileSystem) { Status = gBS->HandleProtocol (File->EfiHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); if (!EFI_ERROR (Status)) { Status = Fs->OpenVolume (Fs, &Root); if (!EFI_ERROR (Status)) { // Get information about the volume Size = 0; Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); if (Status == EFI_BUFFER_TOO_SMALL) { File->FsInfo = AllocatePool (Size); Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); } // Get information about the file Status = Root->Open (Root, &File->FsFileHandle, UnicodeFileName, OpenMode, 0); if (!EFI_ERROR (Status)) { Size = 0; Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { File->FsFileInfo = AllocatePool (Size); Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, File->FsFileInfo); if (!EFI_ERROR (Status)) { File->Size = (UINTN)File->FsFileInfo->FileSize; File->MaxPosition = (UINT64)File->Size; } } } Root->Close (Root); } } } else if (File->Type == EfiOpenBlockIo) { File->Size = (UINTN)File->MaxPosition; } 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]; } } } } }
/** Update the legacy BBS boot option. VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable is udpated with the new Legacy Boot order. The EFI Variable of "Boot####" and gEfiGlobalVariableGuid is also updated. @param CallbackData The context data for BMM. @return EFI_SUCCESS The function completed successfully. @retval EFI_NOT_FOUND If VAR_LEGACY_DEV_ORDER and gEfiLegacyDevOrderVariableGuid EFI Variable can be found. @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource **/ EFI_STATUS Var_UpdateBBSOption ( IN BMM_CALLBACK_DATA *CallbackData ) { UINTN Index; UINTN Index2; VOID *BootOptionVar; CHAR16 VarName[100]; UINTN OptionSize; EFI_STATUS Status; UINT32 *Attribute; BM_MENU_OPTION *OptionMenu; UINT8 *LegacyDev; UINT8 *VarData; UINTN VarSize; LEGACY_DEV_ORDER_ENTRY *DevOrder; UINT8 *OriginalPtr; UINT8 *DisMap; UINTN Pos; UINTN Bit; UINT16 *NewOrder; UINT16 Tmp; UINT16 *EnBootOption; UINTN EnBootOptionCount; UINT16 *DisBootOption; UINTN DisBootOptionCount; DisMap = NULL; NewOrder = NULL; switch (CallbackData->BmmPreviousPageId) { case FORM_SET_FD_ORDER_ID: OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; LegacyDev = CallbackData->BmmFakeNvData.LegacyFD; CallbackData->BbsType = BBS_FLOPPY; break; case FORM_SET_HD_ORDER_ID: OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; LegacyDev = CallbackData->BmmFakeNvData.LegacyHD; CallbackData->BbsType = BBS_HARDDISK; break; case FORM_SET_CD_ORDER_ID: OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; LegacyDev = CallbackData->BmmFakeNvData.LegacyCD; CallbackData->BbsType = BBS_CDROM; break; case FORM_SET_NET_ORDER_ID: OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; LegacyDev = CallbackData->BmmFakeNvData.LegacyNET; CallbackData->BbsType = BBS_EMBED_NETWORK; break; default: ASSERT (FORM_SET_BEV_ORDER_ID == CallbackData->BmmPreviousPageId); OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; LegacyDev = CallbackData->BmmFakeNvData.LegacyBEV; CallbackData->BbsType = BBS_BEV_DEVICE; break; } DisMap = CallbackData->BmmOldFakeNVData.DisableMap; Status = EFI_SUCCESS; // // Update the Variable "LegacyDevOrder" // VarData = (UINT8 *) BdsLibGetVariableAndSize ( VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, &VarSize ); if (VarData == NULL) { return EFI_NOT_FOUND; } OriginalPtr = VarData; DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; while (VarData < OriginalPtr + VarSize) { if (DevOrder->BbsType == CallbackData->BbsType) { break; } VarData += sizeof (BBS_TYPE) + DevOrder->Length; DevOrder = (LEGACY_DEV_ORDER_ENTRY *) VarData; } if (VarData >= OriginalPtr + VarSize) { FreePool (OriginalPtr); return EFI_NOT_FOUND; } NewOrder = AllocateZeroPool (DevOrder->Length - sizeof (DevOrder->Length)); if (NewOrder == NULL) { FreePool (OriginalPtr); return EFI_OUT_OF_RESOURCES; } for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { if (0xFF == LegacyDev[Index]) { break; } NewOrder[Index] = LegacyDev[Index]; } // // Only the enable/disable state of each boot device with same device type can be changed, // so we can count on the index information in DevOrder. // DisMap bit array is the only reliable source to check a device's en/dis state, // so we use DisMap to set en/dis state of each item in NewOrder array // for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { Tmp = (UINT16) (DevOrder->Data[Index2] & 0xFF); Pos = Tmp / 8; Bit = 7 - (Tmp % 8); if ((DisMap[Pos] & (1 << Bit)) != 0) { NewOrder[Index] = (UINT16) (0xFF00 | Tmp); Index++; } } CopyMem ( DevOrder->Data, NewOrder, DevOrder->Length - sizeof (DevOrder->Length) ); FreePool (NewOrder); Status = gRT->SetVariable ( VAR_LEGACY_DEV_ORDER, &gEfiLegacyDevOrderVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, VarSize, OriginalPtr ); // // Update BootOrder and Boot####.Attribute // // 1. Re-order the Option Number in BootOrder according to Legacy Dev Order // ASSERT (OptionMenu->MenuNumber == DevOrder->Length / sizeof (UINT16) - 1); OrderLegacyBootOption4SameType ( DevOrder->Data, DevOrder->Length / sizeof (UINT16) - 1, &EnBootOption, &EnBootOptionCount, &DisBootOption, &DisBootOptionCount ); // // 2. Deactivate the DisBootOption and activate the EnBootOption // for (Index = 0; Index < DisBootOptionCount; Index++) { UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", DisBootOption[Index]); BootOptionVar = BdsLibGetVariableAndSize ( VarName, &gEfiGlobalVariableGuid, &OptionSize ); if (BootOptionVar != NULL) { Attribute = (UINT32 *) BootOptionVar; *Attribute &= ~LOAD_OPTION_ACTIVE; Status = gRT->SetVariable ( VarName, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, OptionSize, BootOptionVar ); FreePool (BootOptionVar); } } for (Index = 0; Index < EnBootOptionCount; Index++) { UnicodeSPrint (VarName, sizeof (VarName), L"Boot%04x", EnBootOption[Index]); BootOptionVar = BdsLibGetVariableAndSize ( VarName, &gEfiGlobalVariableGuid, &OptionSize ); if (BootOptionVar != NULL) { Attribute = (UINT32 *) BootOptionVar; *Attribute |= LOAD_OPTION_ACTIVE; Status = gRT->SetVariable ( VarName, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, OptionSize, BootOptionVar ); FreePool (BootOptionVar); } } BOpt_GetBootOptions (CallbackData); FreePool (OriginalPtr); FreePool (EnBootOption); FreePool (DisBootOption); return Status; }
/** Get the imageid of last image block: EFI_HII_IIBT_END_BLOCK when input ImageId is zero, otherwise return the address of the corresponding image block with identifier specified by ImageId. This is a internal function. @param ImageBlock Points to the beginning of a series of image blocks stored in order. @param ImageId If input ImageId is 0, output the image id of the EFI_HII_IIBT_END_BLOCK; else use this id to find its corresponding image block address. @return The image block address when input ImageId is not zero; otherwise return NULL. **/ UINT8* GetImageIdOrAddress ( IN UINT8 *ImageBlock, IN OUT EFI_IMAGE_ID *ImageId ) { EFI_IMAGE_ID ImageIdCurrent; UINT8 *ImageBlockHdr; UINT8 Length8; UINT16 Length16; UINT32 Length32; EFI_HII_IIBT_IMAGE_1BIT_BLOCK Iibt1bit; EFI_HII_IIBT_IMAGE_4BIT_BLOCK Iibt4bit; EFI_HII_IIBT_IMAGE_8BIT_BLOCK Iibt8bit; UINT16 Width; UINT16 Height; ASSERT (ImageBlock != NULL && ImageId != NULL); ImageBlockHdr = ImageBlock; ImageIdCurrent = 1; while (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType != EFI_HII_IIBT_END) { if (*ImageId > 0) { if (*ImageId == ImageIdCurrent) { // // If the found image block is a duplicate block, update the ImageId to // find the previous defined image block. // if (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType == EFI_HII_IIBT_DUPLICATE) { CopyMem (ImageId, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (EFI_IMAGE_ID)); ASSERT (*ImageId != ImageIdCurrent); ImageBlock = ImageBlockHdr; ImageIdCurrent = 1; continue; } return ImageBlock; } if (*ImageId < ImageIdCurrent) { // // Can not find the specified image block in this image. // return NULL; } } switch (((EFI_HII_IMAGE_BLOCK *) ImageBlock)->BlockType) { case EFI_HII_IIBT_EXT1: Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8)); ImageBlock += Length8; ImageIdCurrent++; break; case EFI_HII_IIBT_EXT2: CopyMem ( &Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8), sizeof (UINT16) ); ImageBlock += Length16; ImageIdCurrent++; break; case EFI_HII_IIBT_EXT4: CopyMem ( &Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT8), sizeof (UINT32) ); ImageBlock += Length32; ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_1BIT: case EFI_HII_IIBT_IMAGE_1BIT_TRANS: CopyMem (&Iibt1bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_1BIT_BLOCK) - sizeof (UINT8) + BITMAP_LEN_1_BIT (Iibt1bit.Bitmap.Width, Iibt1bit.Bitmap.Height); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_4BIT: case EFI_HII_IIBT_IMAGE_4BIT_TRANS: CopyMem (&Iibt4bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_4BIT_BLOCK) - sizeof (UINT8) + BITMAP_LEN_4_BIT (Iibt4bit.Bitmap.Width, Iibt4bit.Bitmap.Height); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_8BIT: case EFI_HII_IIBT_IMAGE_8BIT_TRANS: CopyMem (&Iibt8bit, ImageBlock, sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_8BIT_BLOCK) - sizeof (UINT8) + BITMAP_LEN_8_BIT (Iibt8bit.Bitmap.Width, Iibt8bit.Bitmap.Height); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_24BIT: case EFI_HII_IIBT_IMAGE_24BIT_TRANS: CopyMem (&Width, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16)); CopyMem ( &Height, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK) + sizeof (UINT16), sizeof (UINT16) ); ImageBlock += sizeof (EFI_HII_IIBT_IMAGE_24BIT_BLOCK) - sizeof (EFI_HII_RGB_PIXEL) + BITMAP_LEN_24_BIT (Width, Height); ImageIdCurrent++; break; case EFI_HII_IIBT_DUPLICATE: ImageBlock += sizeof (EFI_HII_IIBT_DUPLICATE_BLOCK); ImageIdCurrent++; break; case EFI_HII_IIBT_IMAGE_JPEG: CopyMem (&Length32, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT32)); ImageBlock += Length32; ImageIdCurrent++; break; case EFI_HII_IIBT_SKIP1: Length8 = *(ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK)); ImageBlock += sizeof (EFI_HII_IIBT_SKIP1_BLOCK); ImageIdCurrent = (UINT16) (ImageIdCurrent + Length8); break; case EFI_HII_IIBT_SKIP2: CopyMem (&Length16, ImageBlock + sizeof (EFI_HII_IMAGE_BLOCK), sizeof (UINT16)); ImageBlock += sizeof (EFI_HII_IIBT_SKIP2_BLOCK); ImageIdCurrent = (UINT16) (ImageIdCurrent + Length16); break; default: // // Unknown image blocks can not be skipped, processing halts. // ASSERT (FALSE); } } // // When ImageId is zero, return the imageid of last image block: EFI_HII_IIBT_END_BLOCK. // if (*ImageId == 0) { *ImageId = ImageIdCurrent; return ImageBlock; } return NULL; }
/** This function create a currently loaded Boot Option from the BMM. It then appends this Boot Option to the end of the "BootOrder" list. It also append this Boot Opotion to the end of BootOptionMenu. @param CallbackData The BMM context data. @param NvRamMap The file explorer formset internal state. @retval EFI_OUT_OF_RESOURCES If not enought memory to complete the operation. @retval EFI_SUCCESS If function completes successfully. **/ EFI_STATUS Var_UpdateBootOption ( IN BMM_CALLBACK_DATA *CallbackData, IN FILE_EXPLORER_NV_DATA *NvRamMap ) { UINT16 *BootOrderList; UINT16 *NewBootOrderList; UINTN BootOrderListSize; UINT16 BootString[10]; VOID *Buffer; UINTN BufferSize; UINT8 *Ptr; UINT16 Index; BM_MENU_ENTRY *NewMenuEntry; BM_LOAD_CONTEXT *NewLoadContext; BOOLEAN OptionalDataExist; EFI_STATUS Status; OptionalDataExist = FALSE; Index = BOpt_GetBootOptionNumber () ; UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index); if (NvRamMap->DescriptionData[0] == 0x0000) { StrCpy (NvRamMap->DescriptionData, BootString); } BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData); BufferSize += GetDevicePathSize (CallbackData->LoadContext->FilePathList); if (NvRamMap->OptionalData[0] != 0x0000) { OptionalDataExist = TRUE; BufferSize += StrSize (NvRamMap->OptionalData); } Buffer = AllocateZeroPool (BufferSize); if (NULL == Buffer) { return EFI_OUT_OF_RESOURCES; } NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; NewLoadContext->Deleted = FALSE; NewLoadContext->LoadOptionSize = BufferSize; Ptr = (UINT8 *) Buffer; NewLoadContext->LoadOption = Ptr; *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; NewLoadContext->Attributes = *((UINT32 *) Ptr); NewLoadContext->IsActive = TRUE; NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); Ptr += sizeof (UINT32); *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); Ptr += sizeof (UINT16); CopyMem ( Ptr, NvRamMap->DescriptionData, StrSize (NvRamMap->DescriptionData) ); NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData)); ASSERT (NewLoadContext->Description != NULL); NewMenuEntry->DisplayString = NewLoadContext->Description; CopyMem ( NewLoadContext->Description, (VOID *) Ptr, StrSize (NvRamMap->DescriptionData) ); Ptr += StrSize (NvRamMap->DescriptionData); CopyMem ( Ptr, CallbackData->LoadContext->FilePathList, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); ASSERT (NewLoadContext->FilePathList != NULL); CopyMem ( NewLoadContext->FilePathList, (VOID *) Ptr, GetDevicePathSize (CallbackData->LoadContext->FilePathList) ); NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); NewMenuEntry->OptionNumber = Index; NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( CallbackData, BootOptionStrDepository ); NewMenuEntry->DisplayStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL); NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( CallbackData, BootOptionHelpStrDepository ); NewMenuEntry->HelpStringToken = HiiSetString (CallbackData->FeHiiHandle, 0, NewMenuEntry->HelpString, NULL); if (OptionalDataExist) { Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData)); } Status = gRT->SetVariable ( BootString, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, BufferSize, Buffer ); ASSERT_EFI_ERROR (Status); BootOrderList = BdsLibGetVariableAndSize ( L"BootOrder", &gEfiGlobalVariableGuid, &BootOrderListSize ); ASSERT (BootOrderList != NULL); NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16)); ASSERT (NewBootOrderList != NULL); CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize); NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index; if (BootOrderList != NULL) { FreePool (BootOrderList); } Status = gRT->SetVariable ( L"BootOrder", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, BootOrderListSize + sizeof (UINT16), NewBootOrderList ); ASSERT_EFI_ERROR (Status); FreePool (NewBootOrderList); NewBootOrderList = NULL; InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); BootOptionMenu.MenuNumber++; NvRamMap->DescriptionData[0] = 0x0000; NvRamMap->OptionalData[0] = 0x0000; return EFI_SUCCESS; }
EFI_STATUS EFIAPI WinNtSerialIoDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ Routine Description: Arguments: Returns: None --*/ // TODO: This - add argument and description to function comment // TODO: Handle - add argument and description to function comment // TODO: RemainingDevicePath - add argument and description to function comment // TODO: EFI_SUCCESS - add return value to function comment // TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; EFI_WIN_NT_IO_PROTOCOL *WinNtIo; WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; HANDLE NtHandle; UART_DEVICE_PATH UartNode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; UINTN EntryCount; UINTN Index; EFI_SERIAL_IO_PROTOCOL *SerialIo; UART_DEVICE_PATH *Uart; UINT32 FlowControlMap; UART_FLOW_CONTROL_DEVICE_PATH *FlowControl; EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; UINT32 Control; Private = NULL; NtHandle = INVALID_HANDLE_VALUE; // // Get the Parent Device Path // Status = gBS->OpenProtocol ( Handle, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { return Status; } // // Grab the IO abstraction we need to get any work done // Status = gBS->OpenProtocol ( Handle, &gEfiWinNtIoProtocolGuid, (VOID **) &WinNtIo, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { gBS->CloseProtocol ( Handle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Handle ); return Status; } if (Status == EFI_ALREADY_STARTED) { if (RemainingDevicePath == NULL || IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath is NULL or is the End of Device Path Node // return EFI_SUCCESS; } // // Make sure a child handle does not already exist. This driver can only // produce one child per serial port. // Status = gBS->OpenProtocolInformation ( Handle, &gEfiWinNtIoProtocolGuid, &OpenInfoBuffer, &EntryCount ); if (EFI_ERROR (Status)) { return Status; } Status = EFI_ALREADY_STARTED; for (Index = 0; Index < EntryCount; Index++) { if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { Status = gBS->OpenProtocol ( OpenInfoBuffer[Index].ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo, This->DriverBindingHandle, Handle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { Uart = (UART_DEVICE_PATH *) RemainingDevicePath; Status = SerialIo->SetAttributes ( SerialIo, Uart->BaudRate, SerialIo->Mode->ReceiveFifoDepth, SerialIo->Mode->Timeout, (EFI_PARITY_TYPE) Uart->Parity, Uart->DataBits, (EFI_STOP_BITS_TYPE) Uart->StopBits ); FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (Uart); if (!EFI_ERROR (Status) && IsUartFlowControlNode (FlowControl)) { Status = SerialIo->GetControl (SerialIo, &Control); if (!EFI_ERROR (Status)) { if (FlowControl->FlowControlMap == UART_FLOW_CONTROL_HARDWARE) { Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; } else { Control &= ~EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; } // // Clear the bits that are not allowed to pass to SetControl // Control &= (EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY | EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE | EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE); Status = SerialIo->SetControl (SerialIo, Control); } } } break; } } FreePool (OpenInfoBuffer); return Status; } FlowControl = NULL; FlowControlMap = 0; if (RemainingDevicePath == NULL) { // // Build the device path by appending the UART node to the ParentDevicePath // from the WinNtIo handle. The Uart setings are zero here, since // SetAttribute() will update them to match the default setings. // ZeroMem (&UartNode, sizeof (UART_DEVICE_PATH)); UartNode.Header.Type = MESSAGING_DEVICE_PATH; UartNode.Header.SubType = MSG_UART_DP; SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode, sizeof (UART_DEVICE_PATH)); } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // only scan the specified device by RemainingDevicePath // // // Match the configuration of the RemainingDevicePath. IsHandleSupported() // already checked to make sure the RemainingDevicePath contains settings // that we can support. // CopyMem (&UartNode, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); FlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) NextDevicePathNode (RemainingDevicePath); if (IsUartFlowControlNode (FlowControl)) { FlowControlMap = FlowControl->FlowControlMap; } else { FlowControl = NULL; } } else { // // If RemainingDevicePath is the End of Device Path Node, // skip enumerate any device and return EFI_SUCESSS // return EFI_SUCCESS; } // // Check to see if we can access the hardware device. If it's Open in NT we // will not get access. // NtHandle = WinNtIo->WinNtThunk->CreateFile ( WinNtIo->EnvString, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if (NtHandle == INVALID_HANDLE_VALUE) { Status = EFI_DEVICE_ERROR; goto Error; } // // Construct Private data // Private = AllocatePool (sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA)); if (Private == NULL) { goto Error; } // // This signature must be valid before any member function is called // Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE; Private->NtHandle = NtHandle; Private->ControllerHandle = Handle; Private->Handle = NULL; Private->WinNtThunk = WinNtIo->WinNtThunk; Private->ParentDevicePath = ParentDevicePath; Private->ControllerNameTable = NULL; Private->SoftwareLoopbackEnable = FALSE; Private->HardwareLoopbackEnable = FALSE; Private->HardwareFlowControl = (BOOLEAN) (FlowControlMap == UART_FLOW_CONTROL_HARDWARE); Private->Fifo.First = 0; Private->Fifo.Last = 0; Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE; CopyMem (&Private->UartDevicePath, &UartNode, sizeof (UART_DEVICE_PATH)); AddUnicodeString2 ( "eng", gWinNtSerialIoComponentName.SupportedLanguages, &Private->ControllerNameTable, WinNtIo->EnvString, TRUE ); AddUnicodeString2 ( "en", gWinNtSerialIoComponentName2.SupportedLanguages, &Private->ControllerNameTable, WinNtIo->EnvString, FALSE ); Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION; Private->SerialIo.Reset = WinNtSerialIoReset; Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes; Private->SerialIo.SetControl = WinNtSerialIoSetControl; Private->SerialIo.GetControl = WinNtSerialIoGetControl; Private->SerialIo.Write = WinNtSerialIoWrite; Private->SerialIo.Read = WinNtSerialIoRead; Private->SerialIo.Mode = &Private->SerialIoMode; // // Build the device path by appending the UART node to the ParentDevicePath // from the WinNtIo handle. The Uart setings are zero here, since // SetAttribute() will update them to match the current setings. // Private->DevicePath = AppendDevicePathNode ( ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath ); // // Only produce the FlowControl node when remaining device path has it // if (FlowControl != NULL) { TempDevicePath = Private->DevicePath; if (TempDevicePath != NULL) { Private->DevicePath = AppendDevicePathNode ( TempDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) FlowControl ); FreePool (TempDevicePath); } } if (Private->DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } // // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. // Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK; Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT; Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate; Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits; Private->SerialIoMode.Parity = Private->UartDevicePath.Parity; Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits; // // Issue a reset to initialize the COM port // Status = Private->SerialIo.Reset (&Private->SerialIo); if (EFI_ERROR (Status)) { goto Error; } // // Create new child handle // Status = gBS->InstallMultipleProtocolInterfaces ( &Private->Handle, &gEfiSerialIoProtocolGuid, &Private->SerialIo, &gEfiDevicePathProtocolGuid, Private->DevicePath, NULL ); if (EFI_ERROR (Status)) { goto Error; } // // Open For Child Device // Status = gBS->OpenProtocol ( Handle, &gEfiWinNtIoProtocolGuid, (VOID **) &WinNtIo, This->DriverBindingHandle, Private->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { goto Error; } return EFI_SUCCESS; Error: // // Use the Stop() function to free all resources allocated in Start() // if (Private != NULL) { if (Private->Handle != NULL) { This->Stop (This, Handle, 1, &Private->Handle); } else { if (NtHandle != INVALID_HANDLE_VALUE) { Private->WinNtThunk->CloseHandle (NtHandle); } if (Private->DevicePath != NULL) { FreePool (Private->DevicePath); } FreeUnicodeStringTable (Private->ControllerNameTable); FreePool (Private); } } This->Stop (This, Handle, 0, NULL); return Status; }
EFI_STATUS EFIAPI Ext2DirOpen(IN EFI_FILE *This, OUT EFI_FILE **NewHandle, IN CHAR16 *FileName, IN UINT64 OpenMode, IN UINT64 Attributes) { EFI_STATUS Status; EXT2_FILE_DATA *File; EXT2_VOLUME_DATA *Volume; EXT2_INODE *BaseDirInode; EXT2_INODE_HANDLE CurrentInodeHandle; EXT2_INODE_HANDLE NextInodeHandle; struct ext2_dir_entry DirEntry; UINT32 NextInodeNo; CHAR16 *PathElement; CHAR16 *PathElementEnd; CHAR16 *NextPathElement; UINTN PathElementLength, i; BOOLEAN NamesEqual; #if DEBUG_LEVEL Print(L"Ext2DirOpen: '%s'\n", FileName); #endif File = EXT2_FILE_FROM_FILE_HANDLE(This); Volume = File->InodeHandle.Inode->Volume; if (OpenMode != EFI_FILE_MODE_READ) return EFI_WRITE_PROTECTED; // analyze start of path, pick starting point PathElement = FileName; if (*PathElement == '\\') { BaseDirInode = Volume->RootInode; while (*PathElement == '\\') PathElement++; } else BaseDirInode = File->InodeHandle.Inode; // open inode for directory reading Status = Ext2InodeHandleReopen(BaseDirInode, &CurrentInodeHandle); if (EFI_ERROR(Status)) return Status; // loop over the path // loop invariant: CurrentInodeHandle is an open, rewinded handle to the current inode for (; *PathElement != 0; PathElement = NextPathElement) { // parse next path element PathElementEnd = PathElement; while (*PathElementEnd != 0 && *PathElementEnd != '\\') PathElementEnd++; PathElementLength = PathElementEnd - PathElement; NextPathElement = PathElementEnd; while (*NextPathElement == '\\') NextPathElement++; // check that this actually is a directory if (!S_ISDIR(CurrentInodeHandle.Inode->RawInode->i_mode)) { #if DEBUG_LEVEL == 2 Print(L"Ext2DirOpen: NOT FOUND (not a directory)\n"); #endif Status = EFI_NOT_FOUND; goto bailout; } // check for . and .. NextInodeNo = 0; if (PathElementLength == 1 && PathElement[0] == '.') { NextInodeNo = CurrentInodeHandle.Inode->InodeNo; } else if (PathElementLength == 2 && PathElement[0] == '.' && PathElement[1] == '.') { if (CurrentInodeHandle.Inode->ParentDirInode == NULL) { // EFI spec says: there is no parent for the root // NOTE: the EFI shell relies on this! Status = EFI_NOT_FOUND; goto bailout; } NextInodeNo = CurrentInodeHandle.Inode->ParentDirInode->InodeNo; } // scan the directory for the file while (NextInodeNo == 0) { // read next entry Status = Ext2DirReadEntry(&CurrentInodeHandle, &DirEntry); if (EFI_ERROR(Status)) goto bailout; if (DirEntry.inode == 0) { // end of directory reached #if DEBUG_LEVEL == 2 Print(L"Ext2DirOpen: NOT FOUND (no match)\n"); #endif Status = EFI_NOT_FOUND; goto bailout; } // compare name if (DirEntry.name_len == PathElementLength) { NamesEqual = TRUE; for (i = 0; i < DirEntry.name_len; i++) { if (DirEntry.name[i] != PathElement[i]) { NamesEqual = FALSE; break; } } if (NamesEqual) NextInodeNo = DirEntry.inode; } } #if DEBUG_LEVEL == 2 Print(L"Ext2DirOpen: found inode %d\n", NextInodeNo); #endif // open the inode we found in the directory Status = Ext2InodeHandleOpen(Volume, NextInodeNo, CurrentInodeHandle.Inode, &DirEntry, &NextInodeHandle); if (EFI_ERROR(Status)) goto bailout; // TODO: resolve symbolic links somehow // close the previous inode handle and replace it with the new one Status = Ext2InodeHandleClose(&CurrentInodeHandle); CopyMem(&CurrentInodeHandle, &NextInodeHandle, sizeof(EXT2_INODE_HANDLE)); } // wrap the current inode into a file handle Status = Ext2FileFromInodeHandle(&CurrentInodeHandle, NewHandle); if (EFI_ERROR(Status)) return Status; // NOTE: file handle takes ownership of inode handle #if DEBUG_LEVEL == 2 Print(L"Ext2DirOpen: returning\n"); #endif return Status; bailout: Ext2InodeHandleClose(&CurrentInodeHandle); return Status; }
/** Initialize or brutally reset the operational parameters for this EFI HTTP instance. The Configure() function does the following: When HttpConfigData is not NULL Initialize this EFI HTTP instance by configuring timeout, local address, port, etc. When HttpConfigData is NULL, reset this EFI HTTP instance by closing all active connections with remote hosts, canceling all asynchronous tokens, and flush request and response buffers without informing the appropriate hosts. No other EFI HTTP function can be executed by this instance until the Configure() function is executed and returns successfully. @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. @param[in] HttpConfigData Pointer to the configure data to configure the instance. @retval EFI_SUCCESS Operation succeeded. @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: This is NULL. HttpConfigData is NULL. HttpConfigData->LocalAddressIsIPv6 is FALSE and HttpConfigData->IPv4Node is NULL. HttpConfigData->LocalAddressIsIPv6 is TRUE and HttpConfigData->IPv6Node is NULL. @retval EFI_ALREADY_STARTED Reinitialize this HTTP instance without calling Configure() with NULL to reset it. @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when executing Configure(). @retval EFI_UNSUPPORTED One or more options in HttpConfigData are not supported in the implementation. **/ EFI_STATUS EFIAPI EfiHttpConfigure ( IN EFI_HTTP_PROTOCOL *This, IN EFI_HTTP_CONFIG_DATA *HttpConfigData ) { HTTP_PROTOCOL *HttpInstance; EFI_STATUS Status; // // Check input parameters. // if (This == NULL || HttpConfigData == NULL || ((HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv6Node == NULL) || (!HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv4Node == NULL))) { return EFI_INVALID_PARAMETER; } HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This); ASSERT (HttpInstance != NULL && HttpInstance->Service != NULL); if (HttpConfigData != NULL) { // // Now configure this HTTP instance. // if (HttpInstance->State != HTTP_STATE_UNCONFIGED) { return EFI_ALREADY_STARTED; } HttpInstance->HttpVersion = HttpConfigData->HttpVersion; HttpInstance->TimeOutMillisec = HttpConfigData->TimeOutMillisec; HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6; if (HttpConfigData->LocalAddressIsIPv6) { CopyMem ( &HttpInstance->Ipv6Node, HttpConfigData->AccessPoint.IPv6Node, sizeof (HttpInstance->Ipv6Node) ); } else { CopyMem ( &HttpInstance->IPv4Node, HttpConfigData->AccessPoint.IPv4Node, sizeof (HttpInstance->IPv4Node) ); } // // Creat Tcp child // Status = HttpInitProtocol (HttpInstance, HttpInstance->LocalAddressIsIPv6); if (EFI_ERROR (Status)) { return Status; } HttpInstance->State = HTTP_STATE_HTTP_CONFIGED; return EFI_SUCCESS; } else { // // Reset all the resources related to HttpInsance. // HttpCleanProtocol (HttpInstance); HttpInstance->State = HTTP_STATE_UNCONFIGED; return EFI_SUCCESS; } }