/** Get section entry value. @param[in] Section Section entry list. @param[in] SectionName Section name. @param[in] EntryName Section entry name. @param[out] EntryValue Point to the got entry value. @retval EFI_NOT_FOUND Section is not found. @retval EFI_SUCCESS Section entry value is got. **/ EFI_STATUS UpdateGetProfileString ( IN SECTION_ITEM *Section, IN CHAR8 *SectionName, IN CHAR8 *EntryName, OUT CHAR8 **EntryValue ) { *EntryValue = NULL; while (Section != NULL) { if (AsciiStrCmp ((CONST CHAR8 *) Section->PtrSection, (CONST CHAR8 *) SectionName) == 0) { if (Section->PtrEntry != NULL) { if (AsciiStrCmp ((CONST CHAR8 *) Section->PtrEntry, (CONST CHAR8 *) EntryName) == 0) { break; } } } Section = Section->PtrNext; } if (Section == NULL) { return EFI_NOT_FOUND; } *EntryValue = Section->PtrValue; return EFI_SUCCESS; }
INTN find_entry(CONST CHAR8 *propName, CONST CHAR8 *propValue, DTEntry *entryH) { DeviceTreeNode *nodeP = (DeviceTreeNode *) (VOID *) startingP; UINTN k; if (nodeP->nProperties == 0) return(kError); // End of the list of nodes startingP = (CHAR8 *) (nodeP + 1); // Search current entry for (k = 0; k < nodeP->nProperties; ++k) { DeviceTreeNodeProperty *propP = (DeviceTreeNodeProperty *) (VOID *) startingP; startingP += sizeof (*propP) + ((propP->length + 3) & -4); if (AsciiStrCmp ((CHAR8*)propP->name, (CHAR8*)propName) == 0) { if (propValue == NULL || AsciiStrCmp( (CHAR8*)(propP + 1), (CHAR8*)propValue) == 0) { *entryH = (DTEntry)nodeP; return(kSuccess); } } } // Search child nodes for (k = 0; k < nodeP->nChildren; ++k) { if (find_entry(propName, propValue, entryH) == kSuccess) return(kSuccess); } return(kError); }
VOID Ext2DebugListTree (IN EXT2_DEV *Private, EXT2_EFI_FILE_PRIVATE *PrivateFile) { EXT2_EFI_FILE_PRIVATE *pFile; struct vop_readdir_args ap; int a_eofflag; off_t *a_cookies; ap.a_vp = PrivateFile; struct dirent *dir; void *c; struct uio uio; struct iovec uio_iov; int error; int ino = PrivateFile->File->i_number; //CHAR16 Name[255]; uio_iov.iov_base = AllocateZeroPool (2048); c = uio_iov.iov_base; uio_iov.iov_len = 2048; uio.uio_iov = &uio_iov; uio.uio_offset = 0; uio.uio_resid = 2048; uio.uio_rw = UIO_READ; ap.a_uio = &uio; ap.a_eofflag = &a_eofflag; ap.a_cookies = &a_cookies; ap.a_cred = 0; error = ext2fs_readdir(&ap); dir = (struct dirent *) c; DEBUG ((EFI_D_INFO, "\n *** In folder %s ***\n", PrivateFile->Filename)); while (dir->d_fileno != 0) { Ext2DebugDirent(dir); //AsciiStrToUnicodeStr(dir->d_name, Name); if ((dir->d_fileno != ino) && (AsciiStrCmp(dir->d_name,".") != 0) && (AsciiStrCmp(dir->d_name,"..") != 0)) { error = ext2fs_vget(Private, dir->d_fileno, &pFile); // pFile->Filename = AllocateZeroPool ((1+AsciiStrLen(dir->d_name))*sizeof(CHAR16)); // StrCpy(pFile->Filename, Name); if (pFile->v_type == VREG) { Ext2DebugPrintContent(pFile); } else { Ext2DebugListTree(Private,pFile); } // FreePool(pFile->Filename); FreePool(pFile); } dir = (struct dirent *) ((char *)dir + dir->d_reclen); } }
RealDTEntry FindChild(RealDTEntry cur, CHAR8 *buf) { RealDTEntry child; UINT32 index; CHAR8* str; UINT32 dummy; if (cur->nChildren == 0) { return NULL; } index = 1; child = GetFirstChild(cur); while (1) { if (DTGetProperty(child, "name", (VOID **)&str, &dummy) != kSuccess) { break; } if (AsciiStrCmp((CHAR8*)str, (CHAR8*)buf) == 0) { return child; } if (index >= cur->nChildren) { break; } child = GetNextChild(child); index++; } return NULL; }
/** Search for a file given its name coded in Ascii. When searching through the files of the volume, if a file is currently not open, its name was written on the media and is kept in RAM in the "HwDescription.Footer.Filename[]" field of the file's description. If a file is currently open, its name might not have been written on the media yet, and as the "HwDescription" is a mirror in RAM of what is on the media the "HwDescription.Footer.Filename[]" might be outdated. In that case, the up to date name of the file is stored in the "Info" field of the file's description. @param[in] Instance Pointer to the description of the volume in which the file has to be search for. @param[in] AsciiFileName Name of the file. @param[out] File Pointer to the description of the file if the file was found. @retval EFI_SUCCESS The file was found. @retval EFI_NOT_FOUND The file was not found. **/ EFI_STATUS BootMonGetFileFromAsciiFileName ( IN BOOTMON_FS_INSTANCE *Instance, IN CHAR8* AsciiFileName, OUT BOOTMON_FS_FILE **File ) { LIST_ENTRY *Entry; BOOTMON_FS_FILE *FileEntry; CHAR8 OpenFileAsciiFileName[MAX_NAME_LENGTH]; CHAR8 *AsciiFileNameToCompare; // Go through all the files in the list and return the file handle for (Entry = GetFirstNode (&Instance->RootFile->Link); !IsNull (&Instance->RootFile->Link, Entry); Entry = GetNextNode (&Instance->RootFile->Link, Entry) ) { FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry); if (FileEntry->Info != NULL) { UnicodeStrToAsciiStr (FileEntry->Info->FileName, OpenFileAsciiFileName); AsciiFileNameToCompare = OpenFileAsciiFileName; } else { AsciiFileNameToCompare = FileEntry->HwDescription.Footer.Filename; } if (AsciiStrCmp (AsciiFileNameToCompare, AsciiFileName) == 0) { *File = FileEntry; return EFI_SUCCESS; } } return EFI_NOT_FOUND; }
EFI_STATUS FixDataMatchingTag( CHAR8* buffer, CHAR8* tag,UINT32* lenPtr) { EFI_STATUS Status; UINT32 length; UINT32 start; UINT32 stop; CHAR8* endTag; start = 0; while (1) { Status = GetNextTag(((UINT8 *)buffer) + start, &endTag, &stop,&length); if (EFI_ERROR(Status)) return Status; if ((*endTag == '/') && !AsciiStrCmp(endTag + 1, tag)) break; start += length; } buffer[start + stop] = '\0'; *lenPtr=start + length; return EFI_SUCCESS; }
STATIC EFI_STATUS SetFileName ( IN BOOTMON_FS_FILE *File, IN CHAR16 *FileNameUnicode ) { CHAR8 *FileNameAscii; UINT16 SavedChar; UINTN FileNameSize; BOOTMON_FS_FILE *SameFile; EFI_STATUS Status; // EFI Shell inserts '\' in front of the filename that must be stripped if (FileNameUnicode[0] == L'\\') { FileNameUnicode++; } // // Convert Unicode into Ascii // SavedChar = L'\0'; FileNameSize = StrLen (FileNameUnicode) + 1; FileNameAscii = AllocatePool (FileNameSize * sizeof (CHAR8)); if (FileNameAscii == NULL) { return EFI_OUT_OF_RESOURCES; } // If Unicode string is too long then truncate it. if (FileNameSize > MAX_NAME_LENGTH) { SavedChar = FileNameUnicode[MAX_NAME_LENGTH - 1]; FileNameUnicode[MAX_NAME_LENGTH - 1] = L'\0'; } UnicodeStrToAsciiStr (FileNameUnicode, FileNameAscii); // If the unicode string was truncated then restore its original content. if (SavedChar != L'\0') { FileNameUnicode[MAX_NAME_LENGTH - 1] = SavedChar; } // If we're changing the file name if (AsciiStrCmp (FileNameAscii, File->HwDescription.Footer.Filename) == 0) { // No change to filename. Status = EFI_SUCCESS; } else if (!(File->OpenMode & EFI_FILE_MODE_WRITE)) { // You can only change the filename if you open the file for write. Status = EFI_ACCESS_DENIED; } else if (BootMonGetFileFromAsciiFileName ( File->Instance, File->HwDescription.Footer.Filename, &SameFile) != EFI_NOT_FOUND) { // A file with that name already exists. Status = EFI_ACCESS_DENIED; } else { // OK, change the filename. AsciiStrCpy (FileNameAscii, File->HwDescription.Footer.Filename); Status = EFI_SUCCESS; } FreePool (FileNameAscii); return Status; }
EFI_STATUS ArmFastbootPlatformGetVar ( IN CHAR8 *Name, OUT CHAR8 *Value ) { if (AsciiStrCmp (Name, "product")) { AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor)); } else { *Value = '\0'; } return EFI_SUCCESS; }
BOOLEAN SettingBoolGet ( CONST CHAR8* Name ) { CHAR8* Value = UtilGetEFIDroidVariable(Name); if (!Value) return FALSE; BOOLEAN Ret = (!AsciiStrCmp(Value, "1")); FreePool(Value); return Ret; }
/** Compare a standalone key against a user structure containing an embedded key. @param[in] StandaloneKey Pointer to the bare key. @param[in] UserStruct Pointer to the user structure with the embedded key. @retval <0 If StandaloneKey compares less than UserStruct's key. @retval 0 If StandaloneKey compares equal to UserStruct's key. @retval >0 If StandaloneKey compares greater than UserStruct's key. **/ STATIC INTN EFIAPI BlobKeyCompare ( IN CONST VOID *StandaloneKey, IN CONST VOID *UserStruct ) { CONST BLOB *Blob; Blob = UserStruct; return AsciiStrCmp (StandaloneKey, (CONST CHAR8 *)Blob->File); }
MACHINE_TYPES GetModelFromString ( CHAR8 *ProductName ) { UINTN i; for (i = 0; i < MaxMachineType; ++i) { if (AsciiStrCmp (AppleProductName[i], ProductName) == 0) { return i; } } // return ending enum as "not found" return MaxMachineType; }
/** Check whether the Token is a known one which is uesed by core. @param Token Pointer to a Null-terminated ASCII string @retval TRUE Is a known one used by core. @retval FALSE Not a known one. **/ BOOLEAN IsKnownTokens ( IN CONST CHAR8 *Token ) { if (Token == NULL) { return FALSE; } if (AsciiStrCmp (Token, SEC_TOK) == 0 || AsciiStrCmp (Token, PEI_TOK) == 0 || AsciiStrCmp (Token, DXE_TOK) == 0 || AsciiStrCmp (Token, BDS_TOK) == 0 || AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0 || AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0 || AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0 || AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0 || AsciiStrCmp (Token, START_IMAGE_TOK) == 0 || AsciiStrCmp (Token, PEIM_TOK) == 0) { return TRUE; } else { return FALSE; } }
/** Check whether header field called FieldName is in DeleteList. @param[in] DeleteList Pointer to array of key/value header pairs. @param[in] DeleteCount The number of header pairs. @param[in] FieldName Pointer to header field's name. @return TRUE if FieldName is not in DeleteList, that means this header field is valid. @return FALSE if FieldName is in DeleteList, that means this header field is invalid. **/ BOOLEAN IsValidHttpHeader ( IN CHAR8 *DeleteList[], IN UINTN DeleteCount, IN CHAR8 *FieldName ) { UINTN Index; for (Index = 0; Index < DeleteCount; Index++) { if (AsciiStrCmp (FieldName, DeleteList[Index]) == 0) { return FALSE; } } return TRUE; }
SymbolPtr FindSymbol( char * string, SymbolPtr * prevSymbol ) { SymbolPtr symbol, prev; symbol = gSymbolsHead; prev = 0; while (symbol != 0) { if (!AsciiStrCmp(symbol->string, string)) break; prev = symbol; symbol = symbol->next; } if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev; return symbol; }
/** Find required header field in HeaderFields. @param[in] HeaderFields Pointer to array of key/value header pairs. @param[in] FieldCount The number of header pairs. @param[in] FieldName Pointer to header field's name. @return Pointer to the queried header field. @return NULL if not find this required header field. **/ EFI_HTTP_HEADER * FindHttpHeader ( IN EFI_HTTP_HEADER *HeaderFields, IN UINTN FieldCount, IN CHAR8 *FieldName ) { UINTN Index; for (Index = 0; Index < FieldCount; Index++) { if (AsciiStrCmp (FieldName, HeaderFields[Index].FieldName) == 0) { // // Find the required header field. // return &HeaderFields[Index]; } } return NULL; }
EFI_STATUS ArmFastbootPlatformOemCommand ( IN CHAR8 *Command ) { CHAR16 CommandUnicode[65]; AsciiStrToUnicodeStr (Command, CommandUnicode); if (AsciiStrCmp (Command, "Demonstrate") == 0) { DEBUG ((EFI_D_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n")); return EFI_SUCCESS; } else { DEBUG ((EFI_D_ERROR, "VExpress: Unrecognised Fastboot OEM command: %s\n", CommandUnicode )); return EFI_NOT_FOUND; } }
INTN DTGetProperty(CONST DTEntry entry, CONST CHAR8 *propertyName, VOID **propertyValue, UINT32 *propertySize) { DeviceTreeNodeProperty *prop; UINTN k; if (entry == NULL || entry->nProperties == 0) { return kError; } else { prop = (DeviceTreeNodeProperty *) (entry + 1); for (k = 0; k < entry->nProperties; k++) { if (AsciiStrCmp((CHAR8*)prop->name, (CHAR8*)propertyName) == 0) { *propertyValue = (VOID *) (((UINT8*)prop) + sizeof(DeviceTreeNodeProperty)); *propertySize = prop->length; return kSuccess; } prop = next_prop(prop); } } return kError; }
TagPtr GetProperty( TagPtr dict, const CHAR8* key ) { TagPtr tagList, tag; if (dict->type != kTagTypeDict) return NULL; tag = 0; tagList = dict->tag; while (tagList) { tag = tagList; tagList = tag->tagNext; if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue; if (!AsciiStrCmp(tag->string, key)) return tag->tag; } return NULL; }
/** Used to translate a device path node to a Target ID and LUN. @param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. @param[in] DevicePath A pointer to a single device path node that describes the SCSI device on the SCSI channel. @param[out] Target A pointer to the Target Array which represents the ID of a SCSI device on the SCSI channel. @param[out] Lun A pointer to the LUN of a SCSI device on the SCSI channel. @retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and LUN, and they were returned in Target and Lun. @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL. @retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN does not exist.Currently not implemented. @retval EFI_UNSUPPORTED This driver does not support the device path node type in DevicePath. **/ EFI_STATUS EFIAPI IScsiExtScsiPassThruGetTargetLun ( IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT UINT8 **Target, OUT UINT64 *Lun ) { ISCSI_DRIVER_DATA *Private; ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData; if ((DevicePath == NULL) || (Target == NULL) || (Lun == NULL)) { return EFI_INVALID_PARAMETER; } if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || (DevicePath->SubType != MSG_ISCSI_DP) || (DevicePathNodeLength (DevicePath) <= sizeof (ISCSI_DEVICE_PATH)) ) { return EFI_UNSUPPORTED; } Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This); ConfigNvData = &Private->Session.ConfigData.NvData; SetMem (*Target, TARGET_MAX_BYTES, 0xFF); (*Target)[0] = 0; if (AsciiStrCmp (ConfigNvData->TargetName, (CHAR8 *) DevicePath + sizeof (ISCSI_DEVICE_PATH)) != 0) { return EFI_UNSUPPORTED; } CopyMem (Lun, ConfigNvData->BootLun, sizeof (UINT64)); return EFI_SUCCESS; }
/** Find the matching SPD with Indexer. @param[in] Selector The pointer to the EFI_IPSEC_SPD_SELECTOR structure. @param[in] Data The pointer to the EFI_IPSEC_SPD_DATA structure. @param[in] Indexer The pointer to the SPD_ENTRY_INDEXER structure. @retval TRUE The matched SPD is found. @retval FALSE The matched SPD is not found. **/ BOOLEAN MatchSpdEntry ( IN EFI_IPSEC_SPD_SELECTOR *Selector, IN EFI_IPSEC_SPD_DATA *Data, IN SPD_ENTRY_INDEXER *Indexer ) { BOOLEAN Match; Match = FALSE; if (Indexer->Name != NULL) { if ((Data->Name != NULL) && (AsciiStrCmp ((CHAR8 *) Indexer->Name, (CHAR8 *) Data->Name) == 0)) { Match = TRUE; } } else { if (Indexer->Index == 0) { Match = TRUE; } Indexer->Index--; } return Match; }
/** Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM ACPI table is "$PV". @param[in, out] Table The TPM item in ACPI table. @param[in] PPVer Version string of Physical Presence interface supported by platform. @return The allocated address for the found region. **/ EFI_STATUS UpdatePPVersion ( EFI_ACPI_DESCRIPTION_HEADER *Table, CHAR8 *PPVer ) { EFI_STATUS Status; UINT8 *DataPtr; // // Patch some pointers for the ASL code before loading the SSDT. // for (DataPtr = (UINT8 *)(Table + 1); DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE); DataPtr += 1) { if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) { Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer); DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status)); return Status; } } return EFI_NOT_FOUND; }
STATIC UINT64 SerialPortGetBaseAddress ( VOID ) { UINT64 BaudRate; UINT32 ReceiveFifoDepth; EFI_PARITY_TYPE Parity; UINT8 DataBits; EFI_STOP_BITS_TYPE StopBits; VOID *DeviceTreeBase; INT32 Node, Prev; INT32 Len; CONST CHAR8 *Compatible; CONST CHAR8 *NodeStatus; CONST CHAR8 *CompatibleItem; CONST UINT64 *RegProperty; UINTN UartBase; RETURN_STATUS Status; DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) { return 0; } // // Enumerate all FDT nodes looking for a PL011 and capture its base address // for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); if (Compatible == NULL) { continue; } // // Iterate over the NULL-separated items in the compatible string // for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len; CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) { if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) { NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len); if (NodeStatus != NULL && AsciiStrCmp (NodeStatus, "okay") != 0) { continue; } RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if (Len != 16) { return 0; } UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty)); BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate); ReceiveFifoDepth = 0; // Use the default value for Fifo depth Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity); DataBits = FixedPcdGet8 (PcdUartDefaultDataBits); StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits); Status = PL011UartInitializePort ( UartBase, FixedPcdGet32 (PL011UartClkInHz), &BaudRate, &ReceiveFifoDepth, &Parity, &DataBits, &StopBits ); if (!EFI_ERROR (Status)) { return UartBase; } } } } return 0; }
int strcmp (const char *s1, const char *s2) { return (int)AsciiStrCmp(s1, s2); }
/** Translate an OpenFirmware device path fragment to a UEFI device path fragment, and advance in the input string. @param[in out] Ptr Address of the pointer pointing to the start of the path string. After successful translation (RETURN_SUCCESS) or at least successful parsing (RETURN_UNSUPPORTED, RETURN_BUFFER_TOO_SMALL), *Ptr is set to the byte immediately following the consumed characters. In other error cases, it points to the byte that caused the error. @param[out] Translated Destination array receiving the UEFI path fragment, allocated by the caller. If the return value differs from RETURN_SUCCESS, its contents is indeterminate. @param[in out] TranslatedSize On input, the number of CHAR16's in Translated. On RETURN_SUCCESS this parameter is assigned the number of non-NUL CHAR16's written to Translated. In case of other return values, TranslatedSize is indeterminate. @retval RETURN_SUCCESS Translation successful. @retval RETURN_BUFFER_TOO_SMALL The OpenFirmware device path was parsed successfully, but its translation did not fit into the number of bytes provided. Further calls to this function are possible. @retval RETURN_UNSUPPORTED The OpenFirmware device path was parsed successfully, but it can't be translated in the current implementation. Further calls to this function are possible. @retval RETURN_NOT_FOUND Translation terminated. On input, *Ptr was pointing to the empty string or "HALT". On output, *Ptr points to the empty string (ie. "HALT" is consumed transparently when present). @retval RETURN_INVALID_PARAMETER Parse error. This is a permanent error. **/ STATIC RETURN_STATUS TranslateOfwPath ( IN OUT CONST CHAR8 **Ptr, OUT CHAR16 *Translated, IN OUT UINTN *TranslatedSize ) { UINTN NumNodes; RETURN_STATUS Status; OFW_NODE Node[EXAMINED_OFW_NODES]; BOOLEAN IsFinal; OFW_NODE Skip; IsFinal = FALSE; NumNodes = 0; if (AsciiStrCmp (*Ptr, "HALT") == 0) { *Ptr += 4; Status = RETURN_NOT_FOUND; } else { Status = ParseOfwNode (Ptr, &Node[NumNodes], &IsFinal); } if (Status == RETURN_NOT_FOUND) { DEBUG ((DEBUG_VERBOSE, "%a: no more nodes\n", __FUNCTION__)); return RETURN_NOT_FOUND; } while (Status == RETURN_SUCCESS && !IsFinal) { ++NumNodes; Status = ParseOfwNode ( Ptr, (NumNodes < EXAMINED_OFW_NODES) ? &Node[NumNodes] : &Skip, &IsFinal ); } switch (Status) { case RETURN_SUCCESS: ++NumNodes; break; case RETURN_INVALID_PARAMETER: DEBUG ((DEBUG_VERBOSE, "%a: parse error\n", __FUNCTION__)); return RETURN_INVALID_PARAMETER; default: ASSERT (0); } Status = TranslateOfwNodes ( Node, NumNodes < EXAMINED_OFW_NODES ? NumNodes : EXAMINED_OFW_NODES, Translated, TranslatedSize); switch (Status) { case RETURN_SUCCESS: DEBUG ((DEBUG_VERBOSE, "%a: success: \"%s\"\n", __FUNCTION__, Translated)); break; case RETURN_BUFFER_TOO_SMALL: DEBUG ((DEBUG_VERBOSE, "%a: buffer too small\n", __FUNCTION__)); break; case RETURN_UNSUPPORTED: DEBUG ((DEBUG_VERBOSE, "%a: unsupported\n", __FUNCTION__)); break; default: ASSERT (0); } return Status; }
EFI_STATUS EFIAPI EblSetCmd ( IN UINTN Argc, IN CHAR8 **Argv ) { EFI_STATUS Status = EFI_INVALID_PARAMETER; CHAR8* AsciiVariableSetting = NULL; CHAR8* AsciiVariableName; CHAR8* AsciiValue; UINT32 AsciiValueLength; CHAR16* VariableName; UINT32 Index; UINT32 EscapedQuotes = 0; BOOLEAN Volatile = FALSE; if (Argc == 1) { AsciiPrint("Variable name is missing.\n"); return Status; } for (Index = 1; Index < Argc; Index++) { if (AsciiStrCmp(Argv[Index],"-v") == 0) { Volatile = 0; } else if (Argv[Index][0] == '-') { AsciiPrint("Warning: '%a' not recognized.\n",Argv[Index]); } else { AsciiVariableSetting = Argv[Index]; } } if (AsciiVariableSetting == NULL) { AsciiPrint("Variable name is missing.\n"); return Status; } // Check if it is a valid variable setting AsciiValue = AsciiStrStr (AsciiVariableSetting,"="); if (AsciiValue == NULL) { // // There is no value. It means this variable will be deleted // // Convert VariableName into Unicode VariableName = AllocatePool((AsciiStrLen (AsciiVariableSetting) + 1) * sizeof (CHAR16)); AsciiStrToUnicodeStr (AsciiVariableSetting,VariableName); Status = gRT->SetVariable ( VariableName, &gEfiGlobalVariableGuid, ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL ); if (!EFI_ERROR(Status)) { AsciiPrint("Variable '%s' deleted\n",VariableName); } else { AsciiPrint("Variable setting is incorrect. It should be VariableName=Value\n"); } return Status; } AsciiValue[0] = '\0'; AsciiVariableName = AsciiVariableSetting; AsciiValue++; // Clean AsciiValue from quote if (AsciiValue[0] == '"') { AsciiValue++; } AsciiValueLength = AsciiStrLen (AsciiValue); if ((AsciiValue[AsciiValueLength-2] != '\\') && (AsciiValue[AsciiValueLength-1] == '"')) { AsciiValue[AsciiValueLength-1] = '\0'; } // Clean AsciiValue from escaped quotes for (Index = 0; Index < AsciiValueLength; Index++) { if ((Index > 0) && (AsciiValue[Index-1] == '\\') && (AsciiValue[Index] == '"')) { EscapedQuotes++; } AsciiValue[Index-EscapedQuotes] = AsciiValue[Index]; } // Fill the end of the value with '\0' for (Index = 0; Index < EscapedQuotes; Index++) { AsciiValue[AsciiValueLength-1-Index] = '\0'; } // Convert VariableName into Unicode VariableName = AllocatePool((AsciiStrLen (AsciiVariableName) + 1) * sizeof (CHAR16)); AsciiStrToUnicodeStr (AsciiVariableName,VariableName); Status = gRT->SetVariable ( VariableName, &gEfiGlobalVariableGuid, ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, AsciiStrLen (AsciiValue)+1, AsciiValue ); if (!EFI_ERROR(Status)) { AsciiPrint("'%a'='%a'\n",AsciiVariableName,AsciiValue); } return Status; }
/** Enable the use of UEFI HTTP boot function. If the driver has already been started but not satisfy the requirement (IP stack and specified boot file path), this function will stop the driver and start it again. @param[in] Private The pointer to the driver's private data. @param[in] UsingIpv6 Specifies the type of IP addresses that are to be used during the session that is being started. Set to TRUE for IPv6, and FALSE for IPv4. @param[in] FilePath The device specific path of the file to load. @retval EFI_SUCCESS HTTP boot was successfully enabled. @retval EFI_INVALID_PARAMETER Private is NULL or FilePath is NULL. @retval EFI_INVALID_PARAMETER The FilePath doesn't contain a valid URI device path node. @retval EFI_ALREADY_STARTED The driver is already in started state. @retval EFI_OUT_OF_RESOURCES There are not enough resources. **/ EFI_STATUS HttpBootStart ( IN HTTP_BOOT_PRIVATE_DATA *Private, IN BOOLEAN UsingIpv6, IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { UINTN Index; EFI_STATUS Status; CHAR8 *Uri; if (Private == NULL || FilePath == NULL) { return EFI_INVALID_PARAMETER; } // // Check the URI in the input FilePath, in order to see whether it is // required to boot from a new specified boot file. // Status = HttpBootParseFilePath (FilePath, &Uri); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } // // Check whether we need to stop and restart the HTTP boot driver. // if (Private->Started) { // // Restart is needed in 2 cases: // 1. Http boot driver has already been started but not on the required IP stack. // 2. The specified boot file URI in FilePath is different with the one we have // recorded before. // if ((UsingIpv6 != Private->UsingIpv6) || ((Uri != NULL) && (AsciiStrCmp (Private->BootFileUri, Uri) != 0))) { // // Restart is required, first stop then continue this start function. // Status = HttpBootStop (Private); if (EFI_ERROR (Status)) { return Status; } } else { // // Restart is not required. // if (Uri != NULL) { FreePool (Uri); } return EFI_ALREADY_STARTED; } } // // Detect whether using ipv6 or not, and set it to the private data. // if (UsingIpv6 && Private->Ip6Nic != NULL) { Private->UsingIpv6 = TRUE; } else if (!UsingIpv6 && Private->Ip4Nic != NULL) { Private->UsingIpv6 = FALSE; } else { if (Uri != NULL) { FreePool (Uri); } return EFI_UNSUPPORTED; } // // Record the specified URI and prepare the URI parser if needed. // Private->FilePathUri = Uri; if (Private->FilePathUri != NULL) { Status = HttpParseUrl ( Private->FilePathUri, (UINT32) AsciiStrLen (Private->FilePathUri), FALSE, &Private->FilePathUriParser ); if (EFI_ERROR (Status)) { FreePool (Private->FilePathUri); return Status; } } // // Init the content of cached DHCP offer list. // ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer)); if (!Private->UsingIpv6) { for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) { Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = HTTP_BOOT_DHCP4_PACKET_MAX_SIZE; } } else { for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) { Private->OfferBuffer[Index].Dhcp6.Packet.Offer.Size = HTTP_BOOT_DHCP6_PACKET_MAX_SIZE; } } if (Private->UsingIpv6) { // // Set Ip6 policy to Automatic to start the Ip6 router discovery. // Status = HttpBootSetIp6Policy (Private); if (EFI_ERROR (Status)) { return Status; } } Private->Started = TRUE; return EFI_SUCCESS; }
/** The Request() function queues an HTTP request to this HTTP instance. Similar to Transmit() function in the EFI TCP driver. When the HTTP request is sent successfully, or if there is an error, Status in token will be updated and Event will be signaled. @param[in] This Pointer to EFI_HTTP_PROTOCOL instance. @param[in] Token Pointer to storage containing HTTP request token. @retval EFI_SUCCESS Outgoing data was processed. @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started. @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. @retval EFI_TIMEOUT Data was dropped out of the transmit or receive queue. @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources. @retval EFI_UNSUPPORTED The HTTP method is not supported in current implementation. @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: This is NULL. Token->Message is NULL. Token->Message->Body is not NULL, Token->Message->BodyLength is non-zero, and Token->Message->Data is NULL, but a previous call to Request()has not been completed successfully. **/ EFI_STATUS EFIAPI EfiHttpRequest ( IN EFI_HTTP_PROTOCOL *This, IN EFI_HTTP_TOKEN *Token ) { EFI_HTTP_MESSAGE *HttpMsg; EFI_HTTP_REQUEST_DATA *Request; VOID *UrlParser; EFI_STATUS Status; CHAR8 *HostName; UINT16 RemotePort; HTTP_PROTOCOL *HttpInstance; BOOLEAN Configure; BOOLEAN ReConfigure; CHAR8 *RequestStr; CHAR8 *Url; CHAR16 *HostNameStr; HTTP_TOKEN_WRAP *Wrap; HTTP_TCP_TOKEN_WRAP *TcpWrap; if ((This == NULL) || (Token == NULL)) { return EFI_INVALID_PARAMETER; } HttpMsg = Token->Message; if ((HttpMsg == NULL) || (HttpMsg->Headers == NULL)) { return EFI_INVALID_PARAMETER; } // // Current implementation does not support POST/PUT method. // If future version supports these two methods, Request could be NULL for a special case that to send large amounts // of data. For this case, the implementation need check whether previous call to Request() has been completed or not. // // Request = HttpMsg->Data.Request; if ((Request == NULL) || (Request->Url == NULL)) { return EFI_INVALID_PARAMETER; } // // Only support GET and HEAD method in current implementation. // if ((Request->Method != HttpMethodGet) && (Request->Method != HttpMethodHead)) { return EFI_UNSUPPORTED; } HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This); ASSERT (HttpInstance != NULL); if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) { return EFI_NOT_STARTED; } if (HttpInstance->LocalAddressIsIPv6) { return EFI_UNSUPPORTED; } // // Check whether the token already existed. // if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTokenExist, Token))) { return EFI_ACCESS_DENIED; } Url = NULL; HostName = NULL; Wrap = NULL; HostNameStr = NULL; TcpWrap = NULL; // // Parse the URI of the remote host. // Url = AllocatePool (StrLen (Request->Url) + 1); if (Url == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStr (Request->Url, Url); UrlParser = NULL; Status = HttpParseUrl (Url, (UINT32) AsciiStrLen (Url), FALSE, &UrlParser); if (EFI_ERROR (Status)) { goto Error1; } RequestStr = NULL; HostName = NULL; Status = HttpUrlGetHostName (Url, UrlParser, &HostName); if (EFI_ERROR (Status)) { goto Error1; } Status = HttpUrlGetPort (Url, UrlParser, &RemotePort); if (EFI_ERROR (Status)) { RemotePort = HTTP_DEFAULT_PORT; } Configure = TRUE; ReConfigure = TRUE; if (HttpInstance->RemoteHost == NULL && HttpInstance->RemotePort == 0) { // // Request() is called the first time. // ReConfigure = FALSE; } else { if ((HttpInstance->RemotePort == RemotePort) && (AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0)) { // // Host Name and port number of the request URL are the same with previous call to Request(). // Check whether previous TCP packet sent out. // if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTcpNotReady, NULL))) { // // Wrap the HTTP token in HTTP_TOKEN_WRAP // Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP)); if (Wrap == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error1; } Wrap->HttpToken = Token; Wrap->HttpInstance = HttpInstance; Status = HttpCreateTcp4TxEvent (Wrap); if (EFI_ERROR (Status)) { goto Error1; } Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap); if (EFI_ERROR (Status)) { goto Error1; } Wrap->TcpWrap.Method = Request->Method; FreePool (Url); FreePool (HostName); // // Queue the HTTP token and return. // return EFI_SUCCESS; } else { // // Use existing TCP instance to transmit the packet. // Configure = FALSE; ReConfigure = FALSE; } } else { // // Need close existing TCP instance and create a new TCP instance for data transmit. // if (HttpInstance->RemoteHost != NULL) { FreePool (HttpInstance->RemoteHost); HttpInstance->RemoteHost = NULL; } } } if (Configure) { // // Parse Url for IPv4 address, if failed, perform DNS resolution. // Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr); if (EFI_ERROR (Status)) { HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (UINT16)); if (HostNameStr == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error1; } AsciiStrToUnicodeStr (HostName, HostNameStr); Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr); FreePool (HostNameStr); if (EFI_ERROR (Status)) { goto Error1; } } // // Save the RemotePort and RemoteHost. // ASSERT (HttpInstance->RemoteHost == NULL); HttpInstance->RemotePort = RemotePort; HttpInstance->RemoteHost = HostName; HostName = NULL; } if (ReConfigure) { // // The request URL is different from previous calls to Request(), close existing TCP instance. // ASSERT (HttpInstance->Tcp4 != NULL); HttpCloseConnection (HttpInstance); EfiHttpCancel (This, NULL); } // // Wrap the HTTP token in HTTP_TOKEN_WRAP // Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP)); if (Wrap == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error1; } Wrap->HttpToken = Token; Wrap->HttpInstance = HttpInstance; Wrap->TcpWrap.Method = Request->Method; if (Configure) { // // Configure TCP instance. // Status = HttpConfigureTcp4 (HttpInstance, Wrap); if (EFI_ERROR (Status)) { goto Error1; } // // Connect TCP. // Status = HttpConnectTcp4 (HttpInstance); if (EFI_ERROR (Status)) { goto Error2; } } else { // // For the new HTTP token, create TX TCP token events. // Status = HttpCreateTcp4TxEvent (Wrap); if (EFI_ERROR (Status)) { goto Error1; } } // // Create request message. // RequestStr = HttpGenRequestString (HttpInstance, HttpMsg, Url); if (RequestStr == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error3; } Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap); if (EFI_ERROR (Status)) { goto Error4; } FreePool (Url); if (HostName != NULL) { FreePool (HostName); } // // Transmit the request message. // Status = HttpTransmitTcp4 ( HttpInstance, Wrap, (UINT8*) RequestStr, AsciiStrLen (RequestStr) ); if (EFI_ERROR (Status)) { goto Error5; } return EFI_SUCCESS; Error5: NetMapRemoveTail (&HttpInstance->TxTokens, NULL); Error4: if (RequestStr != NULL) { FreePool (RequestStr); } Error3: HttpCloseConnection (HttpInstance); Error2: HttpCloseTcp4ConnCloseEvent (HttpInstance); if (NULL != Wrap->TcpWrap.TxToken.CompletionToken.Event) { gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event); } Error1: if (Url != NULL) { FreePool (Url); } if (HostName != NULL) { FreePool (HostName); } if (Wrap != NULL) { FreePool (Wrap); } if (UrlParser!= NULL) { HttpUrlFreeParser (UrlParser); } return Status; }
int OnigStrCmp (char* Str1, char* Str2) { return (int)AsciiStrCmp (Str1, Str2); }
/** Initialize HII information for the FrontPage @param InitializeHiiData TRUE if HII elements need to be initialized. @retval EFI_SUCCESS The operation is successful. @retval EFI_DEVICE_ERROR If the dynamic opcode creation failed. **/ EFI_STATUS InitializeFrontPage ( IN BOOLEAN InitializeHiiData ) { EFI_STATUS Status; CHAR8 *LangCode; CHAR8 *Lang; CHAR8 *CurrentLang; UINTN OptionCount; CHAR16 *StringBuffer; EFI_HII_HANDLE HiiHandle; VOID *OptionsOpCodeHandle; VOID *StartOpCodeHandle; VOID *EndOpCodeHandle; EFI_IFR_GUID_LABEL *StartLabel; EFI_IFR_GUID_LABEL *EndLabel; EFI_HII_STRING_PROTOCOL *HiiString; UINTN StringSize; Lang = NULL; StringBuffer = NULL; if (InitializeHiiData) { // // Initialize the Device Manager // InitializeDeviceManager (); // // Initialize the Device Manager // InitializeBootManager (); gCallbackKey = 0; // // Locate Hii relative protocols // Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &gFormBrowser2); if (EFI_ERROR (Status)) { return Status; } // // Install Device Path Protocol and Config Access protocol to driver handle // Status = gBS->InstallMultipleProtocolInterfaces ( &gFrontPagePrivate.DriverHandle, &gEfiDevicePathProtocolGuid, &mFrontPageHiiVendorDevicePath, &gEfiHiiConfigAccessProtocolGuid, &gFrontPagePrivate.ConfigAccess, NULL ); ASSERT_EFI_ERROR (Status); // // Publish our HII data // gFrontPagePrivate.HiiHandle = HiiAddPackages ( &gFrontPageFormSetGuid, gFrontPagePrivate.DriverHandle, FrontPageVfrBin, BdsDxeStrings, NULL ); if (gFrontPagePrivate.HiiHandle == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Init OpCode Handle and Allocate space for creation of UpdateData Buffer // StartOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (StartOpCodeHandle != NULL); EndOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (EndOpCodeHandle != NULL); OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); ASSERT (OptionsOpCodeHandle != NULL); // // Create Hii Extend Label OpCode as the start opcode // StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; StartLabel->Number = LABEL_SELECT_LANGUAGE; // // Create Hii Extend Label OpCode as the end opcode // EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; EndLabel->Number = LABEL_END; // // Collect the languages from what our current Language support is based on our VFR // HiiHandle = gFrontPagePrivate.HiiHandle; GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL); // // Get Support language list from variable. // if (mLanguageString == NULL){ GetEfiGlobalVariable2 (L"PlatformLangCodes", (VOID**)&mLanguageString, NULL); if (mLanguageString == NULL) { mLanguageString = AllocateCopyPool ( AsciiStrSize ((CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes)), (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLangCodes) ); ASSERT (mLanguageString != NULL); } } if (gFrontPagePrivate.LanguageToken == NULL) { // // Count the language list number. // LangCode = mLanguageString; Lang = AllocatePool (AsciiStrSize (mLanguageString)); ASSERT (Lang != NULL); OptionCount = 0; while (*LangCode != 0) { GetNextLanguage (&LangCode, Lang); OptionCount ++; } // // Allocate extra 1 as the end tag. // gFrontPagePrivate.LanguageToken = AllocateZeroPool ((OptionCount + 1) * sizeof (EFI_STRING_ID)); ASSERT (gFrontPagePrivate.LanguageToken != NULL); Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString); ASSERT_EFI_ERROR (Status); LangCode = mLanguageString; 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)) { StringBuffer = AllocatePool (AsciiStrSize (Lang) * sizeof (CHAR16)); ASSERT (StringBuffer != NULL); AsciiStrToUnicodeStr (Lang, StringBuffer); } ASSERT (StringBuffer != NULL); gFrontPagePrivate.LanguageToken[OptionCount] = HiiSetString (HiiHandle, 0, StringBuffer, NULL); FreePool (StringBuffer); OptionCount++; } } ASSERT (gFrontPagePrivate.LanguageToken != NULL); LangCode = mLanguageString; OptionCount = 0; if (Lang == NULL) { Lang = AllocatePool (AsciiStrSize (mLanguageString)); ASSERT (Lang != NULL); } while (*LangCode != 0) { GetNextLanguage (&LangCode, Lang); if (CurrentLang != NULL && AsciiStrCmp (Lang, CurrentLang) == 0) { HiiCreateOneOfOptionOpCode ( OptionsOpCodeHandle, gFrontPagePrivate.LanguageToken[OptionCount], EFI_IFR_OPTION_DEFAULT, EFI_IFR_NUMERIC_SIZE_1, (UINT8) OptionCount ); } else { HiiCreateOneOfOptionOpCode ( OptionsOpCodeHandle, gFrontPagePrivate.LanguageToken[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 ); Status = HiiUpdateForm ( HiiHandle, &gFrontPageFormSetGuid, FRONT_PAGE_FORM_ID, StartOpCodeHandle, // LABEL_SELECT_LANGUAGE EndOpCodeHandle // LABEL_END ); HiiFreeOpCodeHandle (StartOpCodeHandle); HiiFreeOpCodeHandle (EndOpCodeHandle); HiiFreeOpCodeHandle (OptionsOpCodeHandle); return Status; }
/** This function checks the received iSCSI Login Response during the security negotiation stage. @param[in] Conn The iSCSI connection. @retval EFI_SUCCESS The Login Response passed the CHAP validation. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_PROTOCOL_ERROR Some kind of protocol error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS IScsiCHAPOnRspReceived ( IN ISCSI_CONNECTION *Conn ) { EFI_STATUS Status; ISCSI_SESSION *Session; ISCSI_CHAP_AUTH_DATA *AuthData; CHAR8 *Value; UINT8 *Data; UINT32 Len; LIST_ENTRY *KeyValueList; UINTN Algorithm; CHAR8 *Identifier; CHAR8 *Challenge; CHAR8 *Name; CHAR8 *Response; UINT8 TargetRsp[ISCSI_CHAP_RSP_LEN]; UINT32 RspLen; UINTN Result; ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION); ASSERT (Conn->RspQue.BufNum != 0); Session = Conn->Session; AuthData = &Session->AuthData.CHAP; Len = Conn->RspQue.BufSize; Data = AllocateZeroPool (Len); if (Data == NULL) { return EFI_OUT_OF_RESOURCES; } // // Copy the data in case the data spans over multiple PDUs. // NetbufQueCopy (&Conn->RspQue, 0, Len, Data); // // Build the key-value list from the data segment of the Login Response. // KeyValueList = IScsiBuildKeyValueList ((CHAR8 *) Data, Len); if (KeyValueList == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Status = EFI_PROTOCOL_ERROR; switch (Conn->AuthStep) { case ISCSI_AUTH_INITIAL: // // The first Login Response. // Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_PORTAL_GROUP_TAG); if (Value == NULL) { goto ON_EXIT; } Result = IScsiNetNtoi (Value); if (Result > 0xFFFF) { goto ON_EXIT; } Session->TargetPortalGroupTag = (UINT16) Result; Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_AUTH_METHOD); if (Value == NULL) { goto ON_EXIT; } // // Initiator mandates CHAP authentication but target replies without "CHAP", or // initiator suggets "None" but target replies with some kind of auth method. // if (Session->AuthType == ISCSI_AUTH_TYPE_NONE) { if (AsciiStrCmp (Value, ISCSI_KEY_VALUE_NONE) != 0) { goto ON_EXIT; } } else if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) { if (AsciiStrCmp (Value, ISCSI_AUTH_METHOD_CHAP) != 0) { goto ON_EXIT; } } else { goto ON_EXIT; } // // Transit to CHAP step one. // Conn->AuthStep = ISCSI_CHAP_STEP_ONE; Status = EFI_SUCCESS; break; case ISCSI_CHAP_STEP_TWO: // // The Target replies with CHAP_A=<A> CHAP_I=<I> CHAP_C=<C> // Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_ALGORITHM); if (Value == NULL) { goto ON_EXIT; } Algorithm = IScsiNetNtoi (Value); if (Algorithm != ISCSI_CHAP_ALGORITHM_MD5) { // // Unsupported algorithm is chosen by target. // goto ON_EXIT; } Identifier = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_IDENTIFIER); if (Identifier == NULL) { goto ON_EXIT; } Challenge = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_CHALLENGE); if (Challenge == NULL) { goto ON_EXIT; } // // Process the CHAP identifier and CHAP Challenge from Target. // Calculate Response value. // Result = IScsiNetNtoi (Identifier); if (Result > 0xFF) { goto ON_EXIT; } AuthData->InIdentifier = (UINT32) Result; AuthData->InChallengeLength = ISCSI_CHAP_AUTH_MAX_LEN; IScsiHexToBin ((UINT8 *) AuthData->InChallenge, &AuthData->InChallengeLength, Challenge); Status = IScsiCHAPCalculateResponse ( AuthData->InIdentifier, AuthData->AuthConfig->CHAPSecret, (UINT32) AsciiStrLen (AuthData->AuthConfig->CHAPSecret), AuthData->InChallenge, AuthData->InChallengeLength, AuthData->CHAPResponse ); // // Transit to next step. // Conn->AuthStep = ISCSI_CHAP_STEP_THREE; break; case ISCSI_CHAP_STEP_THREE: // // One way CHAP authentication and the target would like to // authenticate us. // Status = EFI_SUCCESS; break; case ISCSI_CHAP_STEP_FOUR: ASSERT (AuthData->AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL); // // The forth step, CHAP_N=<N> CHAP_R=<R> is received from Target. // Name = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_NAME); if (Name == NULL) { goto ON_EXIT; } Response = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_RESPONSE); if (Response == NULL) { goto ON_EXIT; } RspLen = ISCSI_CHAP_RSP_LEN; IScsiHexToBin (TargetRsp, &RspLen, Response); // // Check the CHAP Name and Response replied by Target. // Status = IScsiCHAPAuthTarget (AuthData, TargetRsp); break; default: break; } ON_EXIT: if (KeyValueList != NULL) { IScsiFreeKeyValueList (KeyValueList); } FreePool (Data); return Status; }