BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2888 *** NetworkPkg\HttpBootDxe\HttpBootClient.c 2020-05-07 22:54:46.000000000 +05-30 --- NetworkPkg\HttpBootDxe\HttpBootClient.c 2020-08-09 21:03:01.000000000 +05-30 *************** *** 1,6 **** --- 1,13 ---- + //*********************************************************************** + //* * + //* Copyright (c) 1985-2020, American Megatrends International LLC. * + //* * + //* All rights reserved. Subject to AMI licensing agreement. * + //* * + //*********************************************************************** /** @file Implementation of the boot file download function. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent *************** *** 45,57 **** Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH; Node->Ipv4.Header.SubType = MSG_IPv4_DP; SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH)); CopyMem (&Node->Ipv4.LocalIpAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS)); Node->Ipv4.RemotePort = Private->Port; Node->Ipv4.Protocol = EFI_IP_PROTO_TCP; ! Node->Ipv4.StaticIpAddress = FALSE; CopyMem (&Node->Ipv4.GatewayIpAddress, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Node->Ipv4.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); } else { Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH)); if (Node == NULL) { return EFI_OUT_OF_RESOURCES; --- 52,67 ---- Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH; Node->Ipv4.Header.SubType = MSG_IPv4_DP; SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH)); CopyMem (&Node->Ipv4.LocalIpAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS)); Node->Ipv4.RemotePort = Private->Port; Node->Ipv4.Protocol = EFI_IP_PROTO_TCP; ! if (Private->UsingStatic) ! Node->Ipv4.StaticIpAddress =TRUE; ! else ! Node->Ipv4.StaticIpAddress = FALSE; CopyMem (&Node->Ipv4.GatewayIpAddress, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Node->Ipv4.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); } else { Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH)); if (Node == NULL) { return EFI_OUT_OF_RESOURCES; *************** *** 325,374 **** EFI_DHCP6_PACKET_OPTION *Option; EFI_IPv6_ADDRESS IpAddr; CHAR8 *HostName; UINTN HostNameSize; CHAR16 *HostNameStr; EFI_STATUS Status; ! ASSERT (Private != NULL); ! ASSERT (Private->SelectIndex != 0); ! SelectIndex = Private->SelectIndex - 1; ! ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM); ! DnsServerIndex = 0; Status = EFI_SUCCESS; HostName = NULL; // // SelectOffer contains the IP address configuration and name server configuration. // HttpOffer contains the boot file URL. // ! SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp6; ! if (Private->FilePathUri == NULL) { ! // ! // In Corporate environment, we need a HttpOffer. ! // ! if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || ! (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns) || ! (SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) { ! HttpOffer = SelectOffer; ! } else { ! ASSERT (Private->SelectProxyType != HttpOfferTypeMax); ! ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0]; ! HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp6; ! } ! Private->BootFileUriParser = HttpOffer->UriParser; ! Private->BootFileUri = (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data; ! } else { ! // ! // In Home environment the BootFileUri comes from the FilePath. ! // ! Private->BootFileUriParser = Private->FilePathUriParser; ! Private->BootFileUri = Private->FilePathUri; ! } ! // // Check the URI scheme. // Status = HttpBootCheckUriScheme (Private->BootFileUri); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "HttpBootDhcp6ExtractUriInfo: %r.\n", Status)); --- 335,397 ---- EFI_DHCP6_PACKET_OPTION *Option; EFI_IPv6_ADDRESS IpAddr; CHAR8 *HostName; UINTN HostNameSize; CHAR16 *HostNameStr; EFI_STATUS Status; ! EFI_IPv6_ADDRESS *Dns; ! UINTN DataSize; ! ASSERT (Private != NULL); ! if (!Private->UsingStatic){ ! ASSERT (Private->SelectIndex != 0); ! SelectIndex = Private->SelectIndex - 1; ! ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM); ! } DnsServerIndex = 0; + DataSize = 0; Status = EFI_SUCCESS; HostName = NULL; + Dns = NULL; + if (Private->UsingStatic){ + //Static HttpBoot supports Home Environment Only. + // In Home environment the BootFileUri comes from the FilePath. + // + Private->BootFileUriParser = Private->FilePathUriParser; + Private->BootFileUri = Private->FilePathUri; + }else{ + Dns = NULL; // // SelectOffer contains the IP address configuration and name server configuration. // HttpOffer contains the boot file URL. // ! SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp6; ! if (Private->FilePathUri == NULL ) { ! // ! // In Corporate environment, we need a HttpOffer. ! // ! if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || ! (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns) || ! (SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) { ! HttpOffer = SelectOffer; ! } else { ! ASSERT (Private->SelectProxyType != HttpOfferTypeMax); ! ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0]; ! HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp6; ! } ! Private->BootFileUriParser = HttpOffer->UriParser; ! Private->BootFileUri = (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data; ! } else { ! // ! // In Home environment the BootFileUri comes from the FilePath. ! // ! Private->BootFileUriParser = Private->FilePathUriParser; ! Private->BootFileUri = Private->FilePathUri; ! } ! } // // Check the URI scheme. // Status = HttpBootCheckUriScheme (Private->BootFileUri); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "HttpBootDhcp6ExtractUriInfo: %r.\n", Status)); *************** *** 391,403 **** // // Register the IPv6 gateway address to the network device. // Status = HttpBootSetIp6Gateway (Private); if (EFI_ERROR (Status)) { return Status; ! } if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || (SelectOffer->OfferType == HttpOfferTypeDhcpDns) || (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns)) { Option = SelectOffer->OptList[HTTP_BOOT_DHCP6_IDX_DNS_SERVER]; ASSERT (Option != NULL); --- 414,450 ---- // // Register the IPv6 gateway address to the network device. // Status = HttpBootSetIp6Gateway (Private); if (EFI_ERROR (Status)) { return Status; ! } ! if (Private->UsingStatic){ ! if( Private->DnsServerIp != NULL ){ ! // ! // Configure the default DNS server if server assigned. ! // ! ! DataSize = Private->DnsServerCount * sizeof (EFI_IPv6_ADDRESS); ! Dns = AllocateZeroPool(DataSize); ! for (DnsServerIndex = 0;DnsServerIndex < Private->DnsServerCount;DnsServerIndex++) ! CopyMem(&Dns[DnsServerIndex],&Private->DnsServerIp[DnsServerIndex].v6,sizeof(EFI_IPv6_ADDRESS)); ! Status = HttpBootSetIp6Dns ( ! Private, ! DataSize, ! Dns ! ); ! FreePool(Dns); ! if (EFI_ERROR (Status)) { ! goto Error; ! } ! } ! ! goto StaticBoot; ! } ! if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || (SelectOffer->OfferType == HttpOfferTypeDhcpDns) || (SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns)) { Option = SelectOffer->OptList[HTTP_BOOT_DHCP6_IDX_DNS_SERVER]; ASSERT (Option != NULL); *************** *** 430,441 **** --- 477,489 ---- } // // Extract the HTTP server Ip from URL. This is used to Check route table // whether can send message to HTTP Server Ip through the GateWay. // + StaticBoot: Status = HttpUrlGetIp6 ( Private->BootFileUri, Private->BootFileUriParser, &IpAddr ); *************** *** 523,546 **** EFI_STATUS HttpBootDiscoverBootInfo ( IN OUT HTTP_BOOT_PRIVATE_DATA *Private ) { EFI_STATUS Status; // // Start D.O.R.A/S.A.R.R exchange to acquire station ip address and // other Http boot information. // Status = HttpBootDhcp (Private); if (EFI_ERROR (Status)) { return Status; } if (!Private->UsingIpv6) { ! Status = HttpBootDhcp4ExtractUriInfo (Private); } else { Status = HttpBootDhcp6ExtractUriInfo (Private); } return Status; } --- 571,639 ---- EFI_STATUS HttpBootDiscoverBootInfo ( IN OUT HTTP_BOOT_PRIVATE_DATA *Private ) { EFI_STATUS Status; + EFI_IPv4_ADDRESS *Dns; + UINTN DataSize = 0; + UINT8 DnsServerIndex = 0; + Dns = NULL; // // Start D.O.R.A/S.A.R.R exchange to acquire station ip address and // other Http boot information. // Status = HttpBootDhcp (Private); if (EFI_ERROR (Status)) { return Status; } if (!Private->UsingIpv6) { ! if (!Private->UsingStatic){ ! Status = HttpBootDhcp4ExtractUriInfo (Private); ! } ! else{ ! Private->BootFileUriParser = Private->FilePathUriParser; ! Private->BootFileUri = Private->FilePathUri; ! ! if (Private->DnsServerIp != NULL){ ! DataSize = Private->DnsServerCount * sizeof(EFI_IPv4_ADDRESS); ! Dns = AllocateZeroPool(DataSize); ! for (DnsServerIndex = 0;DnsServerIndex < Private->DnsServerCount;DnsServerIndex++) ! CopyMem(&Dns[DnsServerIndex],&(Private->DnsServerIp[DnsServerIndex].v4),sizeof(EFI_IPv4_ADDRESS)); ! ! Status = HttpBootRegisterIp4Dns ( ! Private, ! DataSize, ! Dns ! ); ! ! FreePool (Dns); ! if (EFI_ERROR (Status)) { ! FreePool (Private->DnsServerIp); ! Private->DnsServerIp = NULL; ! return Status; ! } ! } ! // ! // Extract the port from URL, and use default HTTP port 80 if not provided. ! // ! Status = HttpUrlGetPort ( ! Private->BootFileUri, ! Private->BootFileUriParser, ! &Private->Port ! ); ! if (EFI_ERROR (Status) || Private->Port == 0) { ! Private ->Port = 80; ! } ! // ! // Update the device path to include the IP and boot URI information. ! // ! Status = HttpBootUpdateDevicePath (Private); ! } } else { Status = HttpBootDhcp6ExtractUriInfo (Private); } return Status; } *** NetworkPkg\HttpBootDxe\HttpBootConfig.c 2020-05-07 22:54:46.000000000 +05-30 --- NetworkPkg\HttpBootDxe\HttpBootConfig.c 2020-08-04 15:28:06.000000000 +05-30 *************** *** 1,6 **** --- 1,13 ---- + //*********************************************************************** + //* * + //* Copyright (c) 1985-2020, American Megatrends International LLC. * + //* * + //* All rights reserved. Subject to AMI licensing agreement. * + //* * + //*********************************************************************** /** @file Helper functions for configuring or getting the parameters relating to HTTP Boot. Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent *************** *** 36,72 **** EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; UINTN Length; CHAR8 AsciiUri[URI_STR_MAX_SIZE]; EFI_STATUS Status; UINTN Index; EFI_BOOT_MANAGER_LOAD_OPTION NewOption; ! NewDevicePath = NULL; Node = NULL; TmpDevicePath = NULL; if (StrLen (Description) == 0) { return EFI_INVALID_PARAMETER; } // // Convert the scheme to all lower case. // for (Index = 0; Index < StrLen (Uri); Index++) { ! if (Uri[Index] == L':') { ! break; ! } if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') { Uri[Index] -= (CHAR16)(L'A' - L'a'); } } // ! // Only accept empty URI, or http and https URI. // ! if ((StrLen (Uri) != 0) && (StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 8) != 0)) { return EFI_INVALID_PARAMETER; } // // Create a new device path by appending the IP node and URI node to // the driver's parent device path --- 43,93 ---- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; UINTN Length; CHAR8 AsciiUri[URI_STR_MAX_SIZE]; EFI_STATUS Status; UINTN Index; EFI_BOOT_MANAGER_LOAD_OPTION NewOption; ! EFI_IP_ADDRESS LocalIp; ! EFI_IP_ADDRESS SubnetMask; ! EFI_IP_ADDRESS GatewayIp; ! CHAR16 DebugString[URI_STR_MAX_SIZE]; ! CHAR8 *AsciiUri2; ! ! AsciiUri2 = NULL; NewDevicePath = NULL; Node = NULL; TmpDevicePath = NULL; if (StrLen (Description) == 0) { return EFI_INVALID_PARAMETER; } // // Convert the scheme to all lower case. // for (Index = 0; Index < StrLen (Uri); Index++) { ! if (Uri[Index] == L'/' && Uri[Index + 1] == L'/') { ! break; ! } ! if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') { Uri[Index] -= (CHAR16)(L'A' - L'a'); } } // ! // Only accept empty URI, or http , https URI and Static URI. // ! ! if ((StrLen (Uri) != 0) && StrStr(Uri,L"static")){ ! Private->UsingStatic = TRUE; ! } ! else{ ! Private->UsingStatic = FALSE; ! } ! if ((StrLen (Uri) != 0) && (StrnCmp (Uri, L"http://", 7) != 0) && (StrnCmp (Uri, L"https://", 8) != 0)&& EFI_ERROR(HttpBootCheckStaticUri(Uri)) { return EFI_INVALID_PARAMETER; } // // Create a new device path by appending the IP node and URI node to // the driver's parent device path *************** *** 77,107 **** --- 98,159 ---- Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH; Node->Ipv4.Header.SubType = MSG_IPv4_DP; SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH)); + if (Private->UsingStatic){ + Status = VerifyIpv4Address(Uri,&LocalIp,&SubnetMask,&GatewayIp,DebugString); + if (EFI_ERROR(Status)) + return Status; + CopyMem (&Node->Ipv4.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS)); + Node->Ipv4.RemotePort = Private->Port; + Node->Ipv4.Protocol = EFI_IP_PROTO_TCP; + Node->Ipv4.StaticIpAddress = TRUE; + CopyMem (&Node->Ipv4.GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Node->Ipv4.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS)); + } } else { Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH)); if (Node == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Node->Ipv6.Header.Type = MESSAGING_DEVICE_PATH; Node->Ipv6.Header.SubType = MSG_IPv6_DP; SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH)); + if (Private->UsingStatic){ + Status = VerifyIpv6Address (Uri,&LocalIp,&GatewayIp,DebugString); + if (EFI_ERROR(Status)) + return Status; + Node->Ipv6.PrefixLength = IP6_PREFIX_LENGTH; + Node->Ipv6.RemotePort = Private->Port; + Node->Ipv6.Protocol = EFI_IP_PROTO_TCP; + Node->Ipv6.IpAddressOrigin = 0x03; + CopyMem (&Node->Ipv6.LocalIpAddress, &LocalIp.v6 , sizeof (EFI_IPv6_ADDRESS)); + CopyMem (&Node->Ipv6.GatewayIpAddress, &GatewayIp.v6, sizeof (EFI_IPv6_ADDRESS)); + } } TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node); FreePool (Node); if (TmpDevicePath == NULL) { return EFI_OUT_OF_RESOURCES; } // // Update the URI node with the input boot file URI. // UnicodeStrToAsciiStrS (Uri, AsciiUri, sizeof (AsciiUri)); + //Extract Bootfile uri from Static Uri. + if ((Private->UsingStatic && (AsciiStrStr(AsciiUri,"dns") == NULL))||( AsciiStrStr(AsciiUri,"dhcp"))){ + AsciiUri2 = AsciiStrStr (AsciiUri ,"http"); + if (AsciiUri2 != NULL){ + for (Index =0;AsciiUri2[Index] != ')' && AsciiUri2[Index] != '\0' ;Index++); + AsciiUri2[Index] = '\0'; + AsciiStrCpy(AsciiUri,AsciiUri2); + } + } Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (AsciiUri); Node = AllocatePool (Length); if (Node == NULL) { Status = EFI_OUT_OF_RESOURCES; FreePool (TmpDevicePath); goto ON_EXIT; *************** *** 483,494 **** --- 535,551 ---- return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStrS (Uri, AsciiUri, UriLen); Status = HttpBootCheckUriScheme (AsciiUri); + if (Status == EFI_INVALID_PARAMETER){ + Status = HttpBootCheckStaticUri(Uri); + if (Status == EFI_UNSUPPORTED) + return EFI_INVALID_PARAMETER; + } if (Status == EFI_INVALID_PARAMETER) { DEBUG ((EFI_D_ERROR, "HttpBootFormCallback: %r.\n", Status)); CreatePopUp ( *** NetworkPkg\HttpBootDxe\HttpBootDxe.h 2020-05-07 22:54:46.000000000 +05-30 --- NetworkPkg\HttpBootDxe\HttpBootDxe.h 2020-08-09 21:00:21.000000000 +05-30 *************** *** 1,6 **** --- 1,13 ---- + //*********************************************************************** + //* * + //* Copyright (c) 1985-2020, American Megatrends International LLC. * + //* * + //* All rights reserved. Subject to AMI licensing agreement. * + //* * + //*********************************************************************** /** @file UEFI HTTP boot driver's private data structure and interfaces declaration. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent *************** *** 254,265 **** --- 261,273 ---- UINT32 SelectIndex; UINT32 SelectProxyType; HTTP_BOOT_DHCP_PACKET_CACHE OfferBuffer[HTTP_BOOT_OFFER_MAX_NUM]; UINT32 OfferNum; UINT32 OfferCount[HttpOfferTypeMax]; UINT32 OfferIndex[HttpOfferTypeMax][HTTP_BOOT_OFFER_MAX_NUM]; + BOOLEAN UsingStatic; }; #define HTTP_BOOT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('H', 'B', 'P', 'D') #define HTTP_BOOT_VIRTUAL_NIC_SIGNATURE SIGNATURE_32 ('H', 'B', 'V', 'N') #define HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE(a) CR (a, HTTP_BOOT_PRIVATE_DATA, LoadFile, HTTP_BOOT_PRIVATE_DATA_SIGNATURE) #define HTTP_BOOT_PRIVATE_DATA_FROM_ID(a) CR (a, HTTP_BOOT_PRIVATE_DATA, Id, HTTP_BOOT_PRIVATE_DATA_SIGNATURE) *************** *** 518,524 **** --- 526,665 ---- HttpBootIp6DxeDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL ); + /** + Configure Static Ip Address using Ipconfig2 Protocol + + @param[in] Private Pointer to HTTP boot driver private data. + **/ + EFI_STATUS + StaticHttpBoot(HTTP_BOOT_PRIVATE_DATA *Private); + /** + Get the IPv4 Address and Ipv6 Address from the Input Devicepath. + + + @param[in] FilePath Pointer to the device path which contains IPV4 and IPV6 path node. + + @retval EFI_SUCCESS The IPV4 Address and IPV6 Address successfully assigned to Private variable + EFI_INVALID_PARAMETER If FilePath is Null + EFI_NOT_FOUND If IPV4Address can't be found + **/ + EFI_STATUS + HttpBootParseIpAddress ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN HTTP_BOOT_PRIVATE_DATA *Private + ); + /****** + Get the IPv6Address,GatewayIp6Address using Http Uri given by user, + IPV6(LocalIp6Address,Tcp,static or dhcp,gatewayip6Address)/Dns(IP1,IP2,...,IPn)/Uri(_http://DomainName/xxx.efi) + + @param[in] Buffer URI string of the boot file. + @param[out] LocalIp Ipv6 LocalIp Address is updated statically based on Uri + @param[out] GatewayIp Ipv6 GatewayIp is updated statically based on Uri + @Param[out] String The Error Message. + + @retval EFI_SUCCESS IP Address is translated from String. + @retval EFI_INVALID_PARAMETER Url is not supported http and https + EFI_UNSUPPORTED If IP Address is Invalid and Static Uri is invalid + *******/ + EFI_STATUS + VerifyIpv6Address ( + IN CHAR16 *Buffer, + OUT EFI_IP_ADDRESS *LocalIp, + OUT EFI_IP_ADDRESS *GatewayIp, + OUT CHAR16 *String + ); + /********* + Get the IPv4Address,subnetMask,GatewayIp using Http Uri given by user, + IPV4(ClientAddress,protocol,static or Dhcp,gatewayip,subnetMask)/Dns(DnsIP1,DnsIP2...,IPn)/Uri(_http://DomainName/xxx.efi) + + @param[in] Uri The URI string of the boot file. + @param[out] LocalIP Ipv4 LocalP is updated statically based on Uri + @param[out] SubnetMask Ipv4 SubnetMask is updated statically based on Uri + @param[out] GatewayIp Ipv4 GatewayIp is updated statically based on Uri + @Param[out] String The Error Message. + + @retval EFI_SUCCESS IP Address is translated from String. + @retval EFI_INVALID_PARAMETER Url is not supported http and https + EFI_UNSUPPORTED If IP Addrress and static Uri is invalid + ********/ + EFI_STATUS + VerifyIpv4Address ( + IN CHAR16 *Buffer, + OUT EFI_IP_ADDRESS *LocalIp, + OUT EFI_IP_ADDRESS *SubnetMask, + OUT EFI_IP_ADDRESS *GatewayIp, + OUT CHAR16 *String + ); + /****** + This function checks static Uri given by user. + + @param[in] Buffer The URI string of the boot file. + + @retval EFI_SUCCESS Uri and static IP address are valid. + EFI_UNSUPPORTED Static Uri is invalid Format. + EFI_INVALID_PARAMETER Url is not supported http and https. + *******/ + EFI_STATUS + HttpBootCheckStaticUri(IN CHAR16 *Uri); + /** + Configure Static IPv6 Address using Ip6config Protocol + + @param[in] Private Pointer to HTTP boot driver private data. + **/ + EFI_STATUS StaticHttpIPv6Boot (HTTP_BOOT_PRIVATE_DATA *Private); + + /** + This function will register the IPv4 gateway address to the network device. + + @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. + + @retval EFI_SUCCESS The new IP configuration has been configured successfully. + @retval Others Failed to configure the address. + + **/ + EFI_STATUS + HttpBootRegisterIp4Gateway ( + IN HTTP_BOOT_PRIVATE_DATA *Private + ); + /** + This function will switch the IP4 configuration policy to Static. + + @param[in] Private Pointer to HTTP boot driver private data. + + @retval EFI_SUCCESS The policy is already configured to static. + @retval Others Other error as indicated.. + + **/ + EFI_STATUS + HttpBootSetIp4Policy ( + IN HTTP_BOOT_PRIVATE_DATA *Private + ); + /** + Checks the HttpBoot Mode is static or Dhcp from the Input Devicepath. + And Update Private variable private->usingstatic + + + @param[in] FilePath Pointer to the device path which contains a IPV4 and IPv6 device path node. + + @retval EFI_SUCCESS The IPV4 Address and IPv6 Address are successfully assigned to Private variable + EFI_INVALID_PARAMETER If FilePath is Null + **/ + EFI_STATUS + HttpBootCheckBootType (IN EFI_DEVICE_PATH_PROTOCOL *FilePath,IN HTTP_BOOT_PRIVATE_DATA *Private); + /** + Get the IPv4 and IPv6 Dns Address from Input Uri + + + @param[in] Uri Input Uri from Filepath + @param[in] UsingIPv6 Specifies the type of IP addresses. + @param[in] Private The pointer to the driver's private data. + + @retval EFI_SUCCESS The IPV4 Address and IPv6 Address are successfully assigned to HTTP boot driver private data. + EFI_INVALID_PARAMETER If Uri is not a valid Static Devicepath URI + **/ + EFI_STATUS + HttpBootParseDnsIp(IN CHAR8 *Uri,BOOLEAN UsingIpv6,IN HTTP_BOOT_PRIVATE_DATA *Private); #endif *** NetworkPkg\HttpBootDxe\HttpBootDxe.inf 2020-05-07 22:54:46.000000000 +05-30 --- NetworkPkg\HttpBootDxe\HttpBootDxe.inf 2020-07-24 16:19:43.000000000 +05-30 *************** *** 1,6 **** --- 1,15 ---- + + #*********************************************************************** + #* * + #* Copyright (c) 1985-2020, American Megatrends International LLC. * + #* * + #* All rights reserved. Subject to AMI licensing agreement. * + #* * + #*********************************************************************** + ## @file # This modules produce the Load File Protocol for UEFI HTTP boot. # # Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # *************** *** 38,49 **** --- 47,59 ---- HttpBootSupport.h HttpBootSupport.c HttpBootClient.h HttpBootClient.c HttpBootConfigVfr.vfr HttpBootConfigStrings.uni + HttpBootStatic.c [LibraryClasses] UefiDriverEntryPoint UefiBootServicesTableLib MemoryAllocationLib BaseLib *** NetworkPkg\HttpBootDxe\HttpBootImpl.c 2020-05-07 22:54:46.000000000 +05-30 --- NetworkPkg\HttpBootDxe\HttpBootImpl.c 2020-08-09 20:08:53.000000000 +05-30 *************** *** 1,6 **** --- 1,14 ---- + //*********************************************************************** + //* * + //* Copyright (c) 1985-2020, American Megatrends International LLC. * + //* * + //* All rights reserved. Subject to AMI licensing agreement. * + //* * + //*********************************************************************** + /** @file The implementation of EFI_LOAD_FILE_PROTOCOL for UEFI HTTP boot. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent *************** *** 119,139 **** Uri = NULL; 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) { // --- 127,158 ---- Uri = NULL; if (Private == NULL || FilePath == NULL) { return EFI_INVALID_PARAMETER; } ! // ! // Check If HttpBoot get IP Address from user as statically or from dhcp in the input FilePath, // + Status = HttpBootCheckBootType(FilePath,Private); + if (EFI_ERROR (Status)) { + 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; ! } ! ! if (Private->UsingStatic){ ! Status = HttpBootParseDnsIp(Uri,UsingIpv6,Private); ! if (EFI_ERROR(Status)) ! return Status; ! } // // Check whether we need to stop and restart the HTTP boot driver. // if (Private->Started) { // *************** *** 161,173 **** 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) { --- 180,201 ---- if (Uri != NULL) { FreePool (Uri); } return EFI_ALREADY_STARTED; } } ! ! //Check the IP Address in the input FilePath and ! //update the Ip Address to Private Data ! // ! if (Private->UsingStatic){ ! Status = HttpBootParseIpAddress (FilePath,Private); ! if (EFI_ERROR (Status)) { ! return Status; ! } ! } // // 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) { *************** *** 196,215 **** --- 224,245 ---- } } // // Init the content of cached DHCP offer list. // + if(!Private->UsingStatic){ 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_CACHED_DHCP4_PACKET_MAX_SIZE; } } else { for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) { Private->OfferBuffer[Index].Dhcp6.Packet.Offer.Size = HTTP_CACHED_DHCP6_PACKET_MAX_SIZE; + } } } if (Private->UsingIpv6) { // // Set Ip6 policy to Automatic to start the Ip6 router discovery. *************** *** 252,274 **** return EFI_NOT_STARTED; } Status = EFI_DEVICE_ERROR; if (!Private->UsingIpv6) { ! // // Start D.O.R.A process to get a IPv4 address and other boot information. // ! Status = HttpBootDhcp4Dora (Private); } else { ! // // Start S.A.R.R process to get a IPv6 address and other boot information. // ! Status = HttpBootDhcp6Sarr (Private); ! } ! return Status; } /** Attempt to download the boot file through HTTP message exchange. --- 282,332 ---- return EFI_NOT_STARTED; } Status = EFI_DEVICE_ERROR; if (!Private->UsingIpv6) { ! ! if (!Private->UsingStatic) { ! // // Start D.O.R.A process to get a IPv4 address and other boot information. // ! Status = HttpBootDhcp4Dora (Private); ! }else{ ! Status = HttpBootSetIp4Policy (Private); ! if (EFI_ERROR (Status)) { ! return Status; ! } ! Status = StaticHttpBoot(Private); ! if (EFI_ERROR (Status)) { ! return Status; ! } ! Status = HttpBootRegisterIp4Gateway (Private); ! if (EFI_ERROR (Status)) { ! return Status; ! } ! ! AsciiPrint ("\n Station IP address is "); ! HttpBootShowIp4Addr (&Private->StationIp.v4); ! AsciiPrint ("\n"); ! } ! } else { ! ! if (!Private->UsingStatic){ ! // // Start S.A.R.R process to get a IPv6 address and other boot information. // ! Status = HttpBootDhcp6Sarr (Private); ! }else{ ! Status = StaticHttpIPv6Boot (Private); ! AsciiPrint ("\n Station IPv6 address is "); ! HttpBootShowIp6Addr (&Private->StationIp.v6); ! AsciiPrint ("\n"); ! } ! } return Status; } /** Attempt to download the boot file through HTTP message exchange. *** --- NetworkPkg\HttpBootDxe\HttpBootStatic.c 2020-08-09 21:00:09.000000000 +05-30 *************** *** 0 **** --- 1,650 ---- + //*********************************************************************** + //* * + //* Copyright (c) 1985-2020, American Megatrends International LLC. * + //* * + //* All rights reserved. Subject to AMI licensing agreement. * + //* * + //*********************************************************************** + + /** @file HttpBootStatic.c + Provides the Static Http Boot related functions . + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ + + + #include "HttpBootDxe.h" + #include + + + /** + Get the IPv4 and IPv6 Address from the Input Devicepath. + + + @param[in] FilePath Pointer to the device path which contains a IPV4 and IPV6 device path node. + + @retval EFI_SUCCESS The IPV4 Address and IPv6 Address are successfully assigned to Private variable + EFI_INVALID_PARAMETER If FilePath is Null + **/ + EFI_STATUS + HttpBootParseIpAddress ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN HTTP_BOOT_PRIVATE_DATA *Private + ) + { + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEV_PATH *Node; + + if (FilePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&Private->StationIp, sizeof (EFI_IP_ADDRESS)); + ZeroMem (&Private->SubnetMask, sizeof (EFI_IP_ADDRESS)); + ZeroMem (&Private->GatewayIp, sizeof (EFI_IP_ADDRESS)); + // + // Extract the IPV4 address from the FilePath + // + + TempDevicePath = FilePath; + while (!IsDevicePathEnd (TempDevicePath)) { + + if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (TempDevicePath) == MSG_IPv4_DP)) { + Node = ( EFI_DEV_PATH *)TempDevicePath; + + CopyMem (&Private->StationIp.v4, &Node->Ipv4.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Private->SubnetMask.v4, &Node->Ipv4.SubnetMask , sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Private->GatewayIp.v4, &Node->Ipv4.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS)); + } + else if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) && + (DevicePathSubType (TempDevicePath) == MSG_IPv6_DP)) { + Node = (EFI_DEV_PATH *)TempDevicePath ; + + CopyMem (&Private ->StationIp.v6,&Node ->Ipv6.LocalIpAddress,sizeof (EFI_IPv6_ADDRESS)); + CopyMem (&Private ->GatewayIp.v6,&Node ->Ipv6.GatewayIpAddress,sizeof (EFI_IPv6_ADDRESS)); + } + + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + return EFI_SUCCESS; + } + + /** + The notify function of create event when performing a manual config. + + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. + + **/ + VOID + EFIAPI + IfConfigManualAddressNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) + { + *((BOOLEAN *) Context) = TRUE; + } + /** + Configure Static Ip Address using Ip4config2 Protocol + + @param[in] Private Pointer to HTTP boot driver private data. + **/ + EFI_STATUS + StaticHttpBoot (HTTP_BOOT_PRIVATE_DATA *Private) + { + EFI_EVENT MappedEvt; + BOOLEAN IsAddressOk; + EFI_IP4_CONFIG2_POLICY Policy; + EFI_IP4_CONFIG2_MANUAL_ADDRESS ManualAddress; + EFI_STATUS Status; + UINTN DataSize ; + EFI_IP4_CONFIG2_PROTOCOL *IfCfg ; + EFI_EVENT TimeOutEvt ; + // + // Create events & timers for asynchronous settings. + // + CopyMem (&ManualAddress.Address , &Private->StationIp.v4, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&ManualAddress.SubnetMask , &Private ->SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS)); + + + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimeOutEvt + ); + if (EFI_ERROR(Status)) + return Status; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + IfConfigManualAddressNotify, + &IsAddressOk, + &MappedEvt + ); + if (EFI_ERROR(Status)) + return Status; + + IfCfg = Private->Ip4Config2; + Status = IfCfg->RegisterDataNotify ( + IfCfg, + Ip4Config2DataTypeManualAddress, + MappedEvt + ); + if (EFI_ERROR(Status)) + return Status; + Policy = Ip4Config2PolicyStatic; + Status = IfCfg->SetData ( + IfCfg, + Ip4Config2DataTypePolicy, + sizeof (EFI_IP4_CONFIG2_POLICY), + &Policy + ); + + if (EFI_ERROR(Status)) + return Status; + DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS); + + Status = IfCfg->SetData ( + IfCfg, + Ip4Config2DataTypeManualAddress, + DataSize, + &ManualAddress + ); + if (Status == EFI_NOT_READY) { + gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000); + while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { + if (IsAddressOk) { + Status = EFI_SUCCESS; + break; + } + } + } + + Status = IfCfg->UnregisterDataNotify ( + IfCfg, + Ip4Config2DataTypeManualAddress, + MappedEvt + ); + + return Status; + } + + /** + The notify function of create event when performing a manual config. + + @param[in] Event The event this notify function registered to. + @param[in] Context Pointer to the context data registered to the event. + + **/ + VOID + EFIAPI + IfConfig6ManualAddressNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) + { + *((BOOLEAN *) Context) = TRUE; + } + /** + Configure Static Ipv6 Address using Ip6config Protocol + + @param[in] Private Pointer to HTTP boot driver private data. + **/ + + EFI_STATUS + StaticHttpIPv6Boot (HTTP_BOOT_PRIVATE_DATA *Private) + { + EFI_STATUS Status; + EFI_IP6_CONFIG_PROTOCOL *IfCfg; + EFI_IP6_CONFIG_MANUAL_ADDRESS CfgManAddr; + UINT32 CurDadXmits; + UINTN CurDadXmitsLen; + EFI_IP6_CONFIG_POLICY Policy; + EFI_EVENT TimeOutEvt; + EFI_EVENT MappedEvt; + BOOLEAN IsAddressOk; + + // Set static host ip6 address list. + // This is a asynchronous process. + // + CopyMem (&CfgManAddr.Address,&Private->StationIp.v6,sizeof(EFI_IPv6_ADDRESS)); + CfgManAddr.PrefixLength = IP6_PREFIX_LENGTH; + CfgManAddr.IsAnycast = FALSE ; + + IsAddressOk = FALSE; + IfCfg = Private->Ip6Config; + Status = gBS->CreateEvent ( + EVT_TIMER, + TPL_CALLBACK, + NULL, + NULL, + &TimeOutEvt + ); + if (EFI_ERROR(Status)) + return Status; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + IfConfig6ManualAddressNotify, + &IsAddressOk, + &MappedEvt + ); + if (EFI_ERROR(Status)) + return Status; + + Status = IfCfg->RegisterDataNotify ( + IfCfg, + Ip6ConfigDataTypeManualAddress, + MappedEvt + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Policy = Ip6ConfigPolicyManual; + Status = IfCfg->SetData ( + IfCfg, + Ip6ConfigDataTypePolicy, + sizeof (EFI_IP6_CONFIG_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = IfCfg->SetData ( + IfCfg, + Ip6ConfigDataTypeManualAddress, + sizeof(EFI_IP6_CONFIG_MANUAL_ADDRESS), + &CfgManAddr + ); + + + if (Status == EFI_NOT_READY) { + // + // Get current dad transmits count. + // + CurDadXmitsLen = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS); + Status = IfCfg->GetData ( + IfCfg, + Ip6ConfigDataTypeDupAddrDetectTransmits, + &CurDadXmitsLen, + &CurDadXmits + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000 + 10000000 * CurDadXmits); + + while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { + if (IsAddressOk) { + Status = EFI_SUCCESS; + break; + } + } + } + + Status = IfCfg->SetData ( + IfCfg, + Ip6ConfigDataTypeGateway, + sizeof(EFI_IPv6_ADDRESS), + &Private->GatewayIp.v6 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + ON_EXIT: + + Status = IfCfg->UnregisterDataNotify ( + IfCfg, + Ip6ConfigDataTypeManualAddress, + MappedEvt + ); + + if (EFI_ERROR (Status)) { + return Status; + } + return Status; + + } + /********* + Get the IPv4Address,subnetMask,GatewayIp using Http Uri given by user, + IPV4(ClientAddress,protocol,static or Dhcp ,gatewayip,subnetMask)/Dns(DnsIP1,DnsIP2...,IPn)/Uri(_http://DomainName/xxx.efi) + + @param[in] Uri The URI string of the boot file. + @param[out] LocalIP Ipv4 LocalP is updated statically based on Uri + @param[out] SubnetMask Ipv4 SubnetMask is updated statically based on Uri + @param[out] GatewayIp Ipv4 GatewayIp is updated statically based on Uri + @Param[out] String The Error Message. + + @retval EFI_SUCCESS IP Address is translated from String. + @retval EFI_INVALID_PARAMETER Url is not supported http and https + EFI_UNSUPPORTED If IP Addrress and static Uri is invalid + ********/ + EFI_STATUS + VerifyIpv4Address ( + IN CHAR16 *Buffer, + OUT EFI_IP_ADDRESS *LocalIp, + OUT EFI_IP_ADDRESS *SubnetMask, + OUT EFI_IP_ADDRESS *GatewayIp, + OUT CHAR16 *String + ) + { + CHAR16 *EndPointer; + RETURN_STATUS Status; + EFI_IPv4_ADDRESS Dns; + CHAR8 AsciiUri[URI_STR_MAX_SIZE]; + + if (StrnCmp (Buffer ,L"ipv4(",5)){ + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid Uri Format!"); + return EFI_UNSUPPORTED; + } + Buffer +=StrLen(L"ipv4("); + Status = StrToIpv4Address (Buffer, &EndPointer,&LocalIp->v4,NULL); + if (RETURN_ERROR (Status)){ + StrCpyS (String ,URI_STR_MAX_SIZE,L"Invalid LocalIP address!"); + return EFI_UNSUPPORTED; + } + Buffer = EndPointer; + if (StrnCmp(Buffer,L",tcp,static,",12 ) && StrnCmp(Buffer,L",tcp,dhcp,",10 )){ + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid Uri Format!"); + return EFI_UNSUPPORTED; + } + if (StrnCmp(Buffer,L",tcp,dhcp,",10)) + Buffer +=StrLen(L",tcp,static,"); + else + Buffer +=StrLen(L",tcp,dhcp,"); + + Status = StrToIpv4Address (Buffer,&EndPointer, &GatewayIp->v4,NULL); + if (RETURN_ERROR(Status)) { + StrCpyS (String ,URI_STR_MAX_SIZE,L"Invalid GatewayIP Address!"); + return EFI_UNSUPPORTED; + } + Buffer = EndPointer + 1; + Status = StrToIpv4Address (Buffer,&EndPointer, &SubnetMask->v4,NULL); + if (RETURN_ERROR(Status)) { + StrCpyS (String ,URI_STR_MAX_SIZE,L"Invalid SubnetMask Address!"); + return EFI_UNSUPPORTED; + } + Buffer = EndPointer; + if (StrnCmp(Buffer,L")/uri(",6) && StrnCmp(Buffer,L")/dns(",6)){ + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid Uri Format!"); + return EFI_UNSUPPORTED; + } + if (!StrnCmp(Buffer,L")/dns(",6)) + { + Buffer += StrLen(L")/dns("); + do{ + Status = StrToIpv4Address (Buffer,&EndPointer, &Dns,NULL); + if (RETURN_ERROR(Status)) { + StrCpyS (String ,URI_STR_MAX_SIZE,L"Invalid DnsServerIP Address!"); + return EFI_UNSUPPORTED; + } + Buffer = EndPointer +1; + }while(*EndPointer == L','); + } + if (!StrnCmp (Buffer,L"}/uri(",6)){ + Buffer +=StrLen(L")/uri("); + UnicodeStrToAsciiStrS (Buffer, AsciiUri, URI_STR_MAX_SIZE); + Status = HttpBootCheckUriScheme (AsciiUri); + return Status; + } + + return EFI_SUCCESS; + } + + /****** + Get the IPv6Address,GatewayIp6Address using Http Uri given by user, + IPV6(LocalIp6Address,Tcp,static or dhcp,gatewayip6Address)/Dns(IP1,IP2,...,IPn)/Uri(_http://DomainName/xxx.efi) + + @param[in] Buffer URI string of the boot file. + @param[out] LocalIp Ipv6 LocalIp Address is updated statically based on Uri + @param[out] GatewayIp Ipv6 GatewayIp is updated statically based on Uri + @Param[out] String The Error Message. + + @retval EFI_SUCCESS IP Address is translated from String. + @retval EFI_INVALID_PARAMETER Url is not supported http and https + EFI_UNSUPPORTED If IP Address is Invalid and Static Uri is invalid + *******/ + EFI_STATUS + VerifyIpv6Address ( + IN CHAR16 *Buffer, + OUT EFI_IP_ADDRESS *LocalIp, + OUT EFI_IP_ADDRESS *GatewayIp, + OUT CHAR16 *String + ) + { + + CHAR16 *EndPointer; + RETURN_STATUS Status; + EFI_IPv6_ADDRESS Dns; + CHAR8 AsciiUri[URI_STR_MAX_SIZE]; + + if (StrnCmp (Buffer ,L"ipv6(",5)){ + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid Uri Format!"); + return EFI_UNSUPPORTED; + } + Buffer += StrLen (L"ipv6("); + Status = StrToIpv6Address (Buffer, &EndPointer,&LocalIp->v6,NULL); + if (RETURN_ERROR (Status)){ + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid LocalIP address!"); + return EFI_UNSUPPORTED; + } + Buffer = EndPointer; + if (StrnCmp(Buffer,L",tcp,static,",12) && StrnCmp(Buffer,L",tcp,dhcp,",10)){ + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid Uri Format!"); + return EFI_UNSUPPORTED; + } + if (StrnCmp(Buffer,L",tcp,dhcp,",10)) + Buffer +=StrLen(L",tcp,static,"); + else + Buffer +=StrLen(L",tcp,dhcp,"); + + Status = StrToIpv6Address (Buffer,&EndPointer, &GatewayIp->v6,NULL); + if (RETURN_ERROR (Status) ) { + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid GatewayIP Address!"); + return EFI_UNSUPPORTED; + } + Buffer = EndPointer; + if (StrnCmp(Buffer,L")/uri(",6) && StrnCmp(Buffer,L")/dns(",6)){ + StrCpyS (String ,URI_STR_MAX_SIZE, L"Invalid Uri Format!"); + return EFI_UNSUPPORTED; + } + if (!StrnCmp(Buffer,L")/dns(",6)) + { + Buffer += StrLen(L")/dns("); + do{ + Status = StrToIpv6Address (Buffer,&EndPointer, &Dns,NULL); + if (RETURN_ERROR(Status)) { + StrCpyS (String ,URI_STR_MAX_SIZE,L"Invalid DnsServerIP Address!"); + return EFI_UNSUPPORTED; + } + Buffer = EndPointer +1; + }while(*EndPointer == L','); + } + if (!StrnCmp (Buffer,L"}/uri(",6)){ + Buffer +=StrLen(L")/uri("); + UnicodeStrToAsciiStrS (Buffer, AsciiUri, URI_STR_MAX_SIZE); + Status = HttpBootCheckUriScheme (AsciiUri); + return Status; + } + return EFI_SUCCESS; + } + /****** + This function checks static Uri given by user and returns BOOLEAN(TRUE:valid Uri,FALSE:Invalid Uri) + + @param[in] Buffer The URI string of the boot file. + + @retval SUCCESS Uri and static IP address are valid. + EFI_UNSUPPORTED Static Uri is invalid Format. + EFI_INVALID_PARAMETER Url is not supported http and https + *******/ + EFI_STATUS + HttpBootCheckStaticUri(IN CHAR16 *Uri) + { + EFI_STATUS Status; + EFI_INPUT_KEY Key; + EFI_IP_ADDRESS LocalIp; + EFI_IP_ADDRESS SubnetMask; + EFI_IP_ADDRESS GatewayIp; + CHAR16 ErrorMessage[URI_STR_MAX_SIZE]; + UINTN Index = 0; + + if (StrLen (Uri) == 0) + return EFI_INVALID_PARAMETER; + + for (Index = 0; Index < StrLen (Uri); Index++) { + if (Uri[Index] == L'/' && Uri[Index + 1] == L'/') { + break; + } + if (Uri[Index] >= L'A' && Uri[Index] <= L'Z') { + Uri[Index] -= (CHAR16)(L'A' - L'a'); + } + } + if (StrnCmp (Uri,L"ipv4(",5) == 0){ + Status = VerifyIpv4Address (Uri,&LocalIp,&SubnetMask,&GatewayIp,ErrorMessage); + if (EFI_ERROR(Status)){ + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + ErrorMessage, + NULL + ); + return Status; + } + }else if (StrnCmp (Uri,L"ipv6(",5) == 0){ + Status = VerifyIpv6Address (Uri,&LocalIp,&GatewayIp,ErrorMessage); + if (EFI_ERROR(Status)){ + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + ErrorMessage, + NULL + ); + return Status; + } + }else if ((StrnCmp(Uri, L"http://", 7) != 0) && (StrnCmp(Uri, L"https://", 8) != 0)){ + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Invalid Uri", + NULL + ); + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS ; + } + /** + Checks the HttpBoot Mode is static or Dhcp from the Input Devicepath. + And Update Private Variable Private->UsingStatic + + + @param[in] FilePath Pointer to the device path which contains a IPV4 and IPv6 device path node. + + @retval EFI_SUCCESS The IPV4 Address and IPv6 Address are successfully assigned to Private variable + EFI_INVALID_PARAMETER If FilePath is Null + **/ + EFI_STATUS + HttpBootCheckBootType (IN EFI_DEVICE_PATH_PROTOCOL *FilePath,IN HTTP_BOOT_PRIVATE_DATA *Private) + { + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEV_PATH *Node; + + if (FilePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + TempDevicePath = FilePath; + while (!IsDevicePathEnd (TempDevicePath)) { + if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH)){ + if (DevicePathSubType (TempDevicePath) == MSG_IPv4_DP){ + Node = (EFI_DEV_PATH *)TempDevicePath ; + Private->UsingStatic = Node->Ipv4.StaticIpAddress ; + }else if (DevicePathSubType (TempDevicePath) == MSG_IPv6_DP){ + Node = (EFI_DEV_PATH *)TempDevicePath ; + Private->UsingStatic =(Node->Ipv6.IpAddressOrigin == 0x03) ? TRUE : FALSE; + } + } + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + return EFI_SUCCESS; + } + /** + Get the IPv4 and IPv6 Dns Address from Input Uri + + + @param[in] Uri Input Uri from Filepath + @param[in] UsingIPv6 Specifies the type of IP addresses. + @param[in] Private The pointer to the driver's private data. + + @retval EFI_SUCCESS The IPV4 Address and IPv6 Address are successfully assigned to HTTP boot driver private data. + EFI_INVALID_PARAMETER If Uri is not a valid Static Devicepath URI + **/ + EFI_STATUS + HttpBootParseDnsIp(IN CHAR8 *Uri,BOOLEAN UsingIpv6,IN HTTP_BOOT_PRIVATE_DATA *Private) + { + EFI_STATUS Status; + CHAR16 Uri2[URI_STR_MAX_SIZE]; + UINT32 Index = 0; + UINTN UriStrLength = 0; + CHAR16 *EndPointer; + CHAR16 *Buffer; + UINTN DataSize = 0; + + if (Uri == NULL) + return EFI_SUCCESS; + AsciiStrToUnicodeStrS(Uri,Uri2,URI_STR_MAX_SIZE); + UriStrLength = AsciiStrLen(Uri) + 1; + Status = HttpBootCheckStaticUri(Uri2); + if (EFI_ERROR(Status)) + return Status; + if (Buffer = StrStr(Uri2,L"dns(")) + { + Buffer += 4; + DataSize = sizeof(EFI_IP_ADDRESS) ; + Private->DnsServerIp = AllocateZeroPool(DataSize); + if (UsingIpv6) + Status = StrToIpv6Address (Buffer,&EndPointer,&Private->DnsServerIp[Index++].v6,NULL); + else + Status = StrToIpv4Address (Buffer,&EndPointer,&Private->DnsServerIp[Index++].v4,NULL); + if (EFI_ERROR(Status)){ + FreePool(Private->DnsServerIp); + Private->DnsServerIp = NULL; + return Status; + } + while(*EndPointer == L','){ + Private->DnsServerIp = ReallocatePool(DataSize,DataSize + sizeof(EFI_IP_ADDRESS),Private->DnsServerIp); + if (UsingIpv6) + Status = StrToIpv6Address (Buffer,&EndPointer,&Private->DnsServerIp[Index++].v6,NULL); + else + Status = StrToIpv4Address (Buffer,&EndPointer,&Private->DnsServerIp[Index++].v4,NULL); + if (EFI_ERROR(Status)){ + FreePool(Private->DnsServerIp); + Private->DnsServerIp = NULL; + return Status; + } + Buffer = EndPointer + 1; + }while(*EndPointer == L','); + Private->DnsServerCount = Index; + if (Buffer = StrStr(Uri2,L"http")){ + for (Index =0;Buffer[Index] != L')' && Buffer[Index] != L'\0' ;Index++); + Buffer[Index] = L'\0'; + } + UnicodeStrToAsciiStrS(Buffer,Uri,UriStrLength); + } + return EFI_SUCCESS; + } +