/** Edit an IPv4 address The function displays as a string following the "%d.%d.%d.%d" format the IPv4 address that is passed in and asks the user to modify it. If the resulting string defines a valid IPv4 address, the four bytes of the corresponding IPv4 address are extracted from the string and returned by the function. As long as the user does not define a valid IP address, he is asked for one. He can always escape by pressing ESC. @param[in ] EFI_IP_ADDRESS InIpAddr Input IPv4 address @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if and only if the returned value is equal to EFI_SUCCESS @retval EFI_SUCCESS Update completed @retval EFI_ABORTED Editing aborted by the user @retval EFI_INVALID_PARAMETER The string returned by the user is mal-formated @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource **/ EFI_STATUS EditHIInputIP ( IN EFI_IP_ADDRESS *InIpAddr, OUT EFI_IP_ADDRESS *OutIpAddr ) { EFI_STATUS Status; CHAR16 CmdLine[48]; while (TRUE) { UnicodeSPrint ( CmdLine, 48, L"%d.%d.%d.%d", InIpAddr->v4.Addr[0], InIpAddr->v4.Addr[1], InIpAddr->v4.Addr[2], InIpAddr->v4.Addr[3] ); Status = EditHIInputStr (CmdLine, 48); if (EFI_ERROR (Status)) { return EFI_ABORTED; } Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4); if (Status == EFI_INVALID_PARAMETER) { Print (L"Invalid address\n"); } else { return Status; } } }
/** Helper function called to calculate the prefix length associated with the string containing an Ipv4 or Ipv6 Internet Protocol address. @param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address. @param[out] Addr The pointer to the EFI_IP_ADDRESS_INFO structure to contain the result. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Invalid parameter. @retval Others Other mistake case. **/ EFI_STATUS EfiInetAddrRange ( IN CHAR16 *Ptr, OUT EFI_IP_ADDRESS_INFO *Addr ) { EFI_STATUS Status; if ((Ptr == NULL) || (Addr == NULL)) { return EFI_INVALID_PARAMETER; } Status = NetLibStrToIp4 (Ptr, &Addr->Address.v4); if (!EFI_ERROR (Status)) { if ((UINT32)(*Addr->Address.v4.Addr) == 0) { Addr->PrefixLength = 0; } else { Addr->PrefixLength = 32; } return Status; } Status = NetLibStrToIp6andPrefix (Ptr, &Addr->Address.v6, &Addr->PrefixLength); if (!EFI_ERROR (Status) && (Addr->PrefixLength == 0xFF)) { Addr->PrefixLength = 128; } return Status; }
/** Get an IPv4 address The function asks the user for an IPv4 address. If the input string defines a valid IPv4 address, the four bytes of the corresponding IPv4 address are extracted from the string and returned by the function. As long as the user does not define a valid IP address, he is asked for one. He can always escape by pressing ESC. @param[out] EFI_IP_ADDRESS OutIpAddr Returned IPv4 address. Valid if and only if the returned value is equal to EFI_SUCCESS @retval EFI_SUCCESS Input completed @retval EFI_ABORTED Editing aborted by the user @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resource **/ EFI_STATUS GetHIInputIP ( OUT EFI_IP_ADDRESS *OutIpAddr ) { EFI_STATUS Status; CHAR16 CmdLine[48]; while (TRUE) { CmdLine[0] = '\0'; Status = EditHIInputStr (CmdLine, 48); if (EFI_ERROR (Status)) { return EFI_ABORTED; } Status = NetLibStrToIp4 (CmdLine, &OutIpAddr->v4); if (Status == EFI_INVALID_PARAMETER) { Print (L"Invalid address\n"); } else { return Status; } } }
/** Helper function called to convert a string containing an Ipv4 or Ipv6 Internet Protocol address into a proper address for the EFI_IP_ADDRESS structure. @param[in] Ptr The pointer to the string containing an Ipv4 or Ipv6 Internet Protocol address. @param[out] Ip The pointer to the EFI_IP_ADDRESS structure to contain the result. @retval EFI_SUCCESS The operation completed successfully. @retval EFI_INVALID_PARAMETER Invalid parameter. **/ EFI_STATUS EfiInetAddr2 ( IN CHAR16 *Ptr, OUT EFI_IP_ADDRESS *Ip ) { EFI_STATUS Status; if ((Ptr == NULL) || (Ip == NULL)) { return EFI_INVALID_PARAMETER; } // // Parse the input address as Ipv4 Address first. // Status = NetLibStrToIp4 (Ptr, &Ip->v4); if (!EFI_ERROR (Status)) { return Status; } Status = NetLibStrToIp6 (Ptr, &Ip->v6); return Status; }
/** Function for 'tftp' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). @return SHELL_SUCCESS The 'tftp' command completed successfully. @return SHELL_ABORTED The Shell Library initialization failed. @return SHELL_INVALID_PARAMETER At least one of the command's arguments is not valid. @return SHELL_OUT_OF_RESOURCES A memory allocation failed. @return SHELL_NOT_FOUND Network Interface Card not found or server error or file error. **/ SHELL_STATUS EFIAPI ShellCommandRunTftp ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { SHELL_STATUS ShellStatus; EFI_STATUS Status; LIST_ENTRY *CheckPackage; CHAR16 *ProblemParam; UINTN ParamCount; CONST CHAR16 *UserNicName; BOOLEAN NicFound; CONST CHAR16 *ValueStr; CONST CHAR16 *RemoteFilePath; CHAR8 *AsciiRemoteFilePath; CONST CHAR16 *Walker; CONST CHAR16 *LocalFilePath; EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData; EFI_HANDLE *Handles; UINTN HandleCount; UINTN NicNumber; CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH]; EFI_HANDLE ControllerHandle; EFI_HANDLE Mtftp4ChildHandle; EFI_MTFTP4_PROTOCOL *Mtftp4; UINTN FileSize; VOID *Data; SHELL_FILE_HANDLE FileHandle; ShellStatus = SHELL_INVALID_PARAMETER; ProblemParam = NULL; NicFound = FALSE; AsciiRemoteFilePath = NULL; Handles = NULL; FileSize = 0; // // Initialize the Shell library (we must be in non-auto-init...) // Status = ShellInitialize (); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return SHELL_ABORTED; } // // Parse the command line. // Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE); if (EFI_ERROR (Status)) { if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL) ) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellTftpHiiHandle, L"tftp", ProblemParam ); FreePool (ProblemParam); } else { ASSERT (FALSE); } goto Error; } // // Check the number of parameters // ParamCount = ShellCommandLineGetCount (CheckPackage); if (ParamCount > 4) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellTftpHiiHandle, L"tftp" ); goto Error; } if (ParamCount < 3) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellTftpHiiHandle, L"tftp" ); goto Error; } Mtftp4ConfigData = DefaultMtftp4ConfigData; // // Check the host IPv4 address // ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1); Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellTftpHiiHandle, L"tftp", ValueStr ); goto Error; } RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2); AsciiRemoteFilePath = AllocatePool ( (StrLen (RemoteFilePath) + 1) * sizeof (CHAR8) ); if (AsciiRemoteFilePath == NULL) { ShellStatus = SHELL_OUT_OF_RESOURCES; goto Error; } UnicodeStrToAsciiStr (RemoteFilePath, AsciiRemoteFilePath); if (ParamCount == 4) { LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3); } else { Walker = RemoteFilePath + StrLen (RemoteFilePath); while ((--Walker) >= RemoteFilePath) { if ((*Walker == L'\\') || (*Walker == L'/' ) ) { break; } } LocalFilePath = Walker + 1; } // // Get the name of the Network Interface Card to be used if any. // UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i"); ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l"); if (ValueStr != NULL) { if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) { goto Error; } } ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r"); if (ValueStr != NULL) { if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) { goto Error; } } ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c"); if (ValueStr != NULL) { if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) { goto Error; } } ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t"); if (ValueStr != NULL) { if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) { goto Error; } if (Mtftp4ConfigData.TimeoutValue == 0) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellTftpHiiHandle, L"tftp", ValueStr ); goto Error; } } // // Locate all MTFTP4 Service Binding protocols // ShellStatus = SHELL_NOT_FOUND; Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiManagedNetworkServiceBindingProtocolGuid, NULL, &HandleCount, &Handles ); if (EFI_ERROR (Status) || (HandleCount == 0)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC), gShellTftpHiiHandle ); goto Error; } for (NicNumber = 0; (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS); NicNumber++) { ControllerHandle = Handles[NicNumber]; Data = NULL; Status = GetNicName (ControllerHandle, NicNumber, NicName); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME), gShellTftpHiiHandle, NicNumber, Status ); continue; } if (UserNicName != NULL) { if (StrCmp (NicName, UserNicName) != 0) { continue; } NicFound = TRUE; } Status = CreateServiceChildAndOpenProtocol ( ControllerHandle, &gEfiMtftp4ServiceBindingProtocolGuid, &gEfiMtftp4ProtocolGuid, &Mtftp4ChildHandle, (VOID**)&Mtftp4 ); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL), gShellTftpHiiHandle, NicName, Status ); continue; } Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE), gShellTftpHiiHandle, NicName, Status ); goto NextHandle; } Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE), gShellTftpHiiHandle, RemoteFilePath, NicName, Status ); goto NextHandle; } Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, &Data); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD), gShellTftpHiiHandle, RemoteFilePath, NicName, Status ); goto NextHandle; } if (!EFI_ERROR (ShellFileExists (LocalFilePath))) { ShellDeleteFileByName (LocalFilePath); } Status = ShellOpenFileByName ( LocalFilePath, &FileHandle, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellTftpHiiHandle, L"tftp", LocalFilePath ); goto NextHandle; } Status = ShellWriteFile (FileHandle, &FileSize, Data); if (!EFI_ERROR (Status)) { ShellStatus = SHELL_SUCCESS; } else { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE), gShellTftpHiiHandle, LocalFilePath, Status ); } ShellCloseFile (&FileHandle); NextHandle: if (Data != NULL) { gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (FileSize)); } CloseProtocolAndDestroyServiceChild ( ControllerHandle, &gEfiMtftp4ServiceBindingProtocolGuid, &gEfiMtftp4ProtocolGuid, Mtftp4ChildHandle ); } if ((UserNicName != NULL) && (!NicFound)) { ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND), gShellTftpHiiHandle, UserNicName ); } Error: ShellCommandLineFreeVarList (CheckPackage); if (AsciiRemoteFilePath != NULL) { FreePool (AsciiRemoteFilePath); } if (Handles != NULL) { FreePool (Handles); } return ShellStatus; }