/** Acquire the string associated with the Index from smbios structure and return it. The caller is responsible for free the string buffer. @param OptionalStrStart The start position to search the string @param Index The index of the string to extract @param String The string that is extracted @retval EFI_SUCCESS The function returns EFI_SUCCESS always. **/ EFI_STATUS GetOptionalStringByIndex ( IN CHAR8 *OptionalStrStart, IN UINT8 Index, OUT CHAR16 **String ) { UINTN StrSize; if (Index == 0) { *String = AllocateZeroPool (sizeof (CHAR16)); return EFI_SUCCESS; } StrSize = 0; do { Index--; OptionalStrStart += StrSize; StrSize = AsciiStrSize (OptionalStrStart); } while (OptionalStrStart[StrSize] != 0 && Index != 0); if ((Index != 0) || (StrSize == 1)) { // // Meet the end of strings set but Index is non-zero, or // Find an empty string // *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); } else { *String = AllocatePool (StrSize * sizeof (CHAR16)); AsciiStrToUnicodeStrS (OptionalStrStart, *String, StrSize); } return EFI_SUCCESS; }
/** Set the name of a file. This is a helper function for SetFileInfo(). @param[in] Instance A pointer to the description of the volume the file belongs to. @param[in] File A pointer to the description of the file. @param[in] FileName A pointer to the new name of the file. @retval EFI_SUCCESS The name was set. @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file to a file that is already present. **/ STATIC EFI_STATUS SetFileName ( IN BOOTMON_FS_INSTANCE *Instance, IN BOOTMON_FS_FILE *File, IN CONST CHAR16 *FileName ) { CHAR8 AsciiFileName[MAX_NAME_LENGTH]; BOOTMON_FS_FILE *SameFile; // If the file path start with a \ strip it. The EFI Shell may // insert a \ in front of the file name. if (FileName[0] == L'\\') { FileName++; } UnicodeStrToAsciiStrS (FileName, AsciiFileName, MAX_NAME_LENGTH); if (BootMonGetFileFromAsciiFileName ( File->Instance, AsciiFileName, &SameFile ) != EFI_NOT_FOUND) { // A file with that name already exists. return EFI_ACCESS_DENIED; } else { // OK, change the filename. AsciiStrToUnicodeStrS (AsciiFileName, File->Info->FileName, (File->Info->Size - SIZE_OF_EFI_FILE_INFO) / sizeof (CHAR16)); return EFI_SUCCESS; } }
/** Get SD device model name. @param[in, out] Device The pointer to the SD_DEVICE data structure. @param[in] Cid Pointer to SD_CID data structure. @retval EFI_SUCCESS The function completed successfully **/ EFI_STATUS GetSdModelName ( IN OUT SD_DEVICE *Device, IN SD_CID *Cid ) { CHAR8 String[SD_MODEL_NAME_MAX_LEN]; ZeroMem (String, sizeof (String)); CopyMem (String, Cid->OemId, sizeof (Cid->OemId)); String[sizeof (Cid->OemId)] = ' '; CopyMem (String + sizeof (Cid->OemId) + 1, Cid->ProductName, sizeof (Cid->ProductName)); String[sizeof (Cid->OemId) + sizeof (Cid->ProductName)] = ' '; CopyMem (String + sizeof (Cid->OemId) + sizeof (Cid->ProductName) + 1, Cid->ProductSerialNumber, sizeof (Cid->ProductSerialNumber)); AsciiStrToUnicodeStrS (String, Device->ModelName, sizeof (Device->ModelName) / sizeof (Device->ModelName[0])); return EFI_SUCCESS; }
/** Create Select language menu in the front page with oneof opcode. @param[in] HiiHandle The hii handle for the Uiapp driver. @param[in] StartOpCodeHandle The opcode handle to save the new opcode. **/ VOID UiCreateLanguageMenu ( IN EFI_HII_HANDLE HiiHandle, IN VOID *StartOpCodeHandle ) { CHAR8 *LangCode; CHAR8 *Lang; UINTN LangSize; CHAR8 *CurrentLang; UINTN OptionCount; CHAR16 *StringBuffer; VOID *OptionsOpCodeHandle; UINTN StringSize; EFI_STATUS Status; EFI_HII_STRING_PROTOCOL *HiiString; Lang = NULL; StringBuffer = NULL; // // Init OpCode Handle and Allocate space for creation of UpdateData Buffer // OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (OptionsOpCodeHandle != NULL); GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL); // // Get Support language list from variable. // GetEfiGlobalVariable2 (L"PlatformLangCodes", (VOID**)&gLanguageString, NULL); if (gLanguageString == NULL) { gLanguageString = AllocateCopyPool ( AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)), (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) ); ASSERT (gLanguageString != NULL); } if (gLanguageToken == NULL) { // // Count the language list number. // LangCode = gLanguageString; Lang = AllocatePool (AsciiStrSize (gLanguageString)); ASSERT (Lang != NULL); OptionCount = 0; while (*LangCode != 0) { GetNextLanguage (&LangCode, Lang); OptionCount ++; } // // Allocate extra 1 as the end tag. // gLanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID)); ASSERT (gLanguageToken != NULL); Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString); ASSERT_EFI_ERROR (Status); LangCode = gLanguageString; OptionCount = 0; while (*LangCode != 0) { GetNextLanguage (&LangCode, Lang); StringSize = 0; Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { StringBuffer = AllocateZeroPool (StringSize); ASSERT (StringBuffer != NULL); Status = HiiString->GetString (HiiString, Lang, HiiHandle, PRINTABLE_LANGUAGE_NAME_STRING_ID, StringBuffer, &StringSize, NULL); ASSERT_EFI_ERROR (Status); } if (EFI_ERROR (Status)) { LangSize = AsciiStrSize (Lang); StringBuffer = AllocatePool (LangSize * sizeof (CHAR16)); ASSERT (StringBuffer != NULL); AsciiStrToUnicodeStrS (Lang, StringBuffer, LangSize); } ASSERT (StringBuffer != NULL); gLanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL); FreePool (StringBuffer); OptionCount++; } } ASSERT (gLanguageToken != NULL); LangCode = gLanguageString; OptionCount = 0; if (Lang == NULL) { Lang = AllocatePool (AsciiStrSize (gLanguageString)); ASSERT (Lang != NULL); } while (*LangCode != 0) { GetNextLanguage (&LangCode, Lang); if (CurrentLang != NULL && AsciiStrCmp (Lang, CurrentLang) == 0) { HiiCreateOneOfOptionOpCode ( OptionsOpCodeHandle, gLanguageToken[OptionCount], EFI_IFR_OPTION_DEFAULT, EFI_IFR_NUMERIC_SIZE_1, (UINT8) OptionCount ); gCurrentLanguageIndex = (UINT8) OptionCount; } else { HiiCreateOneOfOptionOpCode ( OptionsOpCodeHandle, gLanguageToken[OptionCount], 0, EFI_IFR_NUMERIC_SIZE_1, (UINT8) OptionCount ); } OptionCount++; } if (CurrentLang != NULL) { FreePool (CurrentLang); } FreePool (Lang); HiiCreateOneOfOpCode ( StartOpCodeHandle, FRONT_PAGE_KEY_LANGUAGE, 0, 0, STRING_TOKEN (STR_LANGUAGE_SELECT), STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), EFI_IFR_FLAG_CALLBACK, EFI_IFR_NUMERIC_SIZE_1, OptionsOpCodeHandle, NULL ); }
/** Try to get the controller's ATA/ATAPI description. @param Handle Controller handle. @return The description string. **/ CHAR16 * BmGetDescriptionFromDiskInfo ( IN EFI_HANDLE Handle ) { UINTN Index; EFI_STATUS Status; EFI_DISK_INFO_PROTOCOL *DiskInfo; UINT32 BufferSize; EFI_ATAPI_IDENTIFY_DATA IdentifyData; EFI_SCSI_INQUIRY_DATA InquiryData; CHAR16 *Description; UINTN Length; CONST UINTN ModelNameLength = 40; CONST UINTN SerialNumberLength = 20; CHAR8 *StrPtr; UINT8 Temp; Description = NULL; Status = gBS->HandleProtocol ( Handle, &gEfiDiskInfoProtocolGuid, (VOID **) &DiskInfo ); if (EFI_ERROR (Status)) { return NULL; } if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoAhciInterfaceGuid) || CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) { BufferSize = sizeof (EFI_ATAPI_IDENTIFY_DATA); Status = DiskInfo->Identify ( DiskInfo, &IdentifyData, &BufferSize ); if (!EFI_ERROR (Status)) { Description = AllocateZeroPool ((ModelNameLength + SerialNumberLength + 2) * sizeof (CHAR16)); ASSERT (Description != NULL); for (Index = 0; Index + 1 < ModelNameLength; Index += 2) { Description[Index] = (CHAR16) IdentifyData.ModelName[Index + 1]; Description[Index + 1] = (CHAR16) IdentifyData.ModelName[Index]; } Length = Index; Description[Length++] = L' '; for (Index = 0; Index + 1 < SerialNumberLength; Index += 2) { Description[Length + Index] = (CHAR16) IdentifyData.SerialNo[Index + 1]; Description[Length + Index + 1] = (CHAR16) IdentifyData.SerialNo[Index]; } Length += Index; Description[Length++] = L'\0'; ASSERT (Length == ModelNameLength + SerialNumberLength + 2); BmEliminateExtraSpaces (Description); } } else if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoScsiInterfaceGuid)) { BufferSize = sizeof (EFI_SCSI_INQUIRY_DATA); Status = DiskInfo->Inquiry ( DiskInfo, &InquiryData, &BufferSize ); if (!EFI_ERROR (Status)) { Description = AllocateZeroPool ((VENDOR_IDENTIFICATION_LENGTH + PRODUCT_IDENTIFICATION_LENGTH + 2) * sizeof (CHAR16)); ASSERT (Description != NULL); // // Per SCSI spec, EFI_SCSI_INQUIRY_DATA.Reserved_5_95[3 - 10] save the Verdor identification // EFI_SCSI_INQUIRY_DATA.Reserved_5_95[11 - 26] save the product identification, // Here combine the vendor identification and product identification to the description. // StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[VENDOR_IDENTIFICATION_OFFSET]); Temp = StrPtr[VENDOR_IDENTIFICATION_LENGTH]; StrPtr[VENDOR_IDENTIFICATION_LENGTH] = '\0'; AsciiStrToUnicodeStrS (StrPtr, Description, VENDOR_IDENTIFICATION_LENGTH + 1); StrPtr[VENDOR_IDENTIFICATION_LENGTH] = Temp; // // Add one space at the middle of vendor information and product information. // Description[VENDOR_IDENTIFICATION_LENGTH] = L' '; StrPtr = (CHAR8 *) (&InquiryData.Reserved_5_95[PRODUCT_IDENTIFICATION_OFFSET]); StrPtr[PRODUCT_IDENTIFICATION_LENGTH] = '\0'; AsciiStrToUnicodeStrS (StrPtr, Description + VENDOR_IDENTIFICATION_LENGTH + 1, PRODUCT_IDENTIFICATION_LENGTH + 1); BmEliminateExtraSpaces (Description); } } return Description; }
/** Show one or all PCDs' info. @param[in] InputPcdName Pointer to PCD name to show. If NULL, show all PCDs' info. @retval EFI_SUCCESS Command completed successfully. @retval EFI_OUT_OF_RESOURCES Not enough resources were available to run the command. @retval EFI_ABORTED Aborted by user. @retval EFI_NOT_FOUND The specified PCD is not found. **/ static EFI_STATUS ProcessPcd ( IN CHAR16 *InputPcdName ) { EFI_STATUS Status; EFI_GUID *TokenSpace; UINTN TokenNumber; EFI_PCD_INFO PcdInfo; BOOLEAN Found; UINTN PcdNameSize; PcdInfo.PcdName = NULL; PcdInfo.PcdSize = 0; PcdInfo.PcdType = 0xFF; Found = FALSE; Print (L"Current system SKU ID: 0x%x\n\n", mPiPcdInfo->GetSku ()); TokenSpace = NULL; do { TokenNumber = 0; do { Status = mPiPcd->GetNextToken (TokenSpace, &TokenNumber); if (!EFI_ERROR (Status) && TokenNumber != 0) { if (TokenSpace == NULL) { // // PCD in default Token Space. // mPcdInfo->GetInfo (TokenNumber, &PcdInfo); } else { mPiPcdInfo->GetInfo (TokenSpace, TokenNumber, &PcdInfo); } if (InputPcdName != NULL) { if (PcdInfo.PcdName == NULL) { continue; } PcdNameSize = AsciiStrSize (PcdInfo.PcdName) * sizeof (CHAR16); if (mTempPcdNameBuffer == NULL) { mTempPcdNameBufferSize = PcdNameSize; mTempPcdNameBuffer = AllocatePool (mTempPcdNameBufferSize); } else if (mTempPcdNameBufferSize < PcdNameSize) { mTempPcdNameBuffer = ReallocatePool (mTempPcdNameBufferSize, PcdNameSize, mTempPcdNameBuffer); mTempPcdNameBufferSize = PcdNameSize; } if (mTempPcdNameBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } AsciiStrToUnicodeStrS (PcdInfo.PcdName, mTempPcdNameBuffer, mTempPcdNameBufferSize / sizeof (CHAR16)); // // Compare the input PCD name with the PCD name in PCD database. // if ((StrStr (mTempPcdNameBuffer, InputPcdName) != NULL) || (mUnicodeCollation != NULL && mUnicodeCollation->MetaiMatch (mUnicodeCollation, mTempPcdNameBuffer, InputPcdName))) { // // Found matched PCD. // DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo); Found = TRUE; } } else { DumpPcdInfo (TokenSpace, TokenNumber, &PcdInfo); } } } while (!EFI_ERROR (Status) && TokenNumber != 0); Status = mPiPcd->GetNextTokenSpace ((CONST EFI_GUID **) &TokenSpace); } while (!EFI_ERROR (Status) && TokenSpace != NULL); if ((InputPcdName != NULL) && !Found) { // // The specified PCD is not found, print error. // Print (L"%EError. %NNo matching PCD found: %s.\n", InputPcdName); return EFI_NOT_FOUND; } return EFI_SUCCESS; }
/** Retrieve the host address using the EFI_DNS4_PROTOCOL. @param[in] Image The handle of the driver image. @param[in] Controller The handle of the controller. @param[in, out] NvData The Session config data structure. @retval EFI_SUCCESS Operation succeeded. @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. @retval EFI_DEVICE_ERROR An unexpected network error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS IScsiDns4 ( IN EFI_HANDLE Image, IN EFI_HANDLE Controller, IN OUT ISCSI_SESSION_CONFIG_NVDATA *NvData ) { EFI_STATUS Status; EFI_DNS4_PROTOCOL *Dns4; EFI_DNS4_CONFIG_DATA Dns4CfgData; EFI_DNS4_COMPLETION_TOKEN Token; BOOLEAN IsDone; EFI_HANDLE Dns4Handle; EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; EFI_IPv4_ADDRESS *DnsServerList; UINTN DnsServerListCount; UINTN DataSize; CHAR16 *HostName; DnsServerList = NULL; DnsServerListCount = 0; Dns4Handle = NULL; Dns4 = NULL; ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN)); // // Get DNS server list from EFI IPv4 Configuration II protocol. // Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2); if (!EFI_ERROR (Status)) { // // Get the required size. // DataSize = 0; Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { DnsServerList = AllocatePool (DataSize); if (DnsServerList == NULL) { return EFI_OUT_OF_RESOURCES; } Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList); if (EFI_ERROR (Status)) { FreePool (DnsServerList); DnsServerList = NULL; } else { DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS); } } } // // Create a DNS child instance and get the protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiDns4ServiceBindingProtocolGuid, &Dns4Handle ); if (EFI_ERROR (Status)) { goto Exit; } Status = gBS->OpenProtocol ( Dns4Handle, &gEfiDns4ProtocolGuid, (VOID **) &Dns4, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Exit; } // // Configure DNS4 instance for the DNS server address and protocol. // ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData)); Dns4CfgData.DnsServerListCount = DnsServerListCount; Dns4CfgData.DnsServerList = DnsServerList; Dns4CfgData.EnableDnsCache = TRUE; IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &NvData->LocalIp); IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &NvData->SubnetMask); Dns4CfgData.Protocol = EFI_IP_PROTO_UDP; Status = Dns4->Configure ( Dns4, &Dns4CfgData ); if (EFI_ERROR (Status)) { goto Exit; } // // Create event to set the is done flag when name resolution is finished. // ZeroMem (&Token, sizeof (Token)); Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, IScsiCommonNotify, &IsDone, &Token.Event ); if (EFI_ERROR (Status)) { goto Exit; } // // Start asynchronous name resolution. // Token.Status = EFI_NOT_READY; IsDone = FALSE; HostName = (CHAR16 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE); if (HostName == NULL) { return EFI_OUT_OF_RESOURCES; } AsciiStrToUnicodeStrS ( NvData->TargetUrl, HostName, ISCSI_NAME_MAX_SIZE ); Status = Dns4->HostNameToIp (Dns4, HostName, &Token); if (EFI_ERROR (Status)) { goto Exit; } while (!IsDone) { Dns4->Poll (Dns4); } // // Name resolution is done, check result. // Status = Token.Status; if (!EFI_ERROR (Status)) { if (Token.RspData.H2AData == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } // // We just return the first IP address from DNS protocol. // IP4_COPY_ADDRESS (&NvData->TargetIp.v4, Token.RspData.H2AData->IpList); Status = EFI_SUCCESS; } Exit: if (Token.Event != NULL) { gBS->CloseEvent (Token.Event); } if (Token.RspData.H2AData != NULL) { if (Token.RspData.H2AData->IpList != NULL) { FreePool (Token.RspData.H2AData->IpList); } FreePool (Token.RspData.H2AData); } if (Dns4 != NULL) { Dns4->Configure (Dns4, NULL); gBS->CloseProtocol ( Dns4Handle, &gEfiDns4ProtocolGuid, Image, Controller ); } if (Dns4Handle != NULL) { NetLibDestroyServiceChild ( Controller, Image, &gEfiDns4ServiceBindingProtocolGuid, Dns4Handle ); } return Status; }