Merge tag 'efi-next-2024-12-04' of https://source.denx.de/u-boot/custodians/u-boot...
authorTom Rini <trini@konsulko.com>
Wed, 4 Dec 2024 15:32:28 +0000 (09:32 -0600)
committerTom Rini <trini@konsulko.com>
Wed, 4 Dec 2024 17:56:00 +0000 (11:56 -0600)
CI: https://source.denx.de/u-boot/custodians/u-boot-efi/-/pipelines/23707

With this pull request support for the EFI_HTTP_PROTOCOL and
EFI_IP4_CONFIG2 protocols are added. This allows EFI applications
to load files via HTTP.

UEFI:
      add efi_dp_from_ipv4 function
      add efi_net_set_addr, efi_net_get_addr functions
      add support for HTTP device path
      set EFI bootdevice device path to HTTP when loaded from wget
      add support to send http requests and parse http headers
      provide EFI_IP4_CONFIG2_PROTOCOL
      provide EFI_HTTP_PROTOCOL
      support IPv4() in device path to text protocol
      provide unit tests for the HTTP and IPv4 Config2 protocols

Network:
      zero terminate string with headers in wget_fill_info()
      zero terminate string with headers in wget_lwip_fill_info()
      pass port and server_name via wget_ctx in lwIP network stack
      let wget_with_dns work with dns disabled

Others:
      Add HTTP and IPV4 Config II protocols to UUID library functions.

1  2 
lib/efi_loader/efi_device_path.c

@@@ -974,6 -974,117 +974,116 @@@ struct efi_device_path __maybe_unused *
        return start;
  }
  
 -      }
 -      else {
+ /**
+  * efi_dp_from_ipv4() - set device path from IPv4 address
+  *
+  * Set the device path to an ethernet device path as provided by
+  * efi_dp_from_eth() concatenated with a device path of subtype
+  * DEVICE_PATH_SUB_TYPE_MSG_IPV4, and an END node.
+  *
+  * @ip:               IPv4 local address
+  * @mask:     network mask
+  * @srv:      IPv4 remote/server address
+  * Return:    pointer to device path, NULL on error
+  */
+ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip,
+                                        struct efi_ipv4_address *mask,
+                                        struct efi_ipv4_address *srv)
+ {
+       struct efi_device_path *dp1, *dp2, *pos;
+       struct {
+               struct efi_device_path_ipv4 ipv4dp;
+               struct efi_device_path end;
+       } dp;
+       memset(&dp.ipv4dp, 0, sizeof(dp.ipv4dp));
+       dp.ipv4dp.dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+       dp.ipv4dp.dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_IPV4;
+       dp.ipv4dp.dp.length = sizeof(dp.ipv4dp);
+       dp.ipv4dp.protocol = 6;
+       if (ip)
+               memcpy(&dp.ipv4dp.local_ip_address, ip, sizeof(*ip));
+       if (mask)
+               memcpy(&dp.ipv4dp.subnet_mask, mask, sizeof(*mask));
+       if (srv)
+               memcpy(&dp.ipv4dp.remote_ip_address, srv, sizeof(*srv));
+       pos = &dp.end;
+       memcpy(pos, &END, sizeof(END));
+       dp1 = efi_dp_from_eth();
+       if (!dp1)
+               return NULL;
+       dp2 = efi_dp_concat(dp1, (const struct efi_device_path *)&dp, 0);
+       efi_free_pool(dp1);
+       return dp2;
+ }
+ /**
+  * efi_dp_from_http() - set device path from http
+  *
+  * Set the device path to an IPv4 path as provided by efi_dp_from_ipv4
+  * concatenated with a device path of subtype DEVICE_PATH_SUB_TYPE_MSG_URI,
+  * and an END node.
+  *
+  * @server:   URI of remote server
+  * Return:    pointer to HTTP device path, NULL on error
+  */
+ struct efi_device_path *efi_dp_from_http(const char *server)
+ {
+       struct efi_device_path *dp1, *dp2;
+       struct efi_device_path_uri *uridp;
+       efi_uintn_t uridp_len;
+       char *pos;
+       char tmp[128];
+       struct efi_ipv4_address ip;
+       struct efi_ipv4_address mask;
+       if ((server && strlen("http://") + strlen(server) + 1  > sizeof(tmp)) ||
+           (!server && IS_ENABLED(CONFIG_NET_LWIP)))
+               return NULL;
+       efi_net_get_addr(&ip, &mask, NULL);
+       dp1 = efi_dp_from_ipv4(&ip, &mask, NULL);
+       if (!dp1)
+               return NULL;
+       strcpy(tmp, "http://");
+       if (server) {
+               strlcat(tmp, server, sizeof(tmp));
+ #if !IS_ENABLED(CONFIG_NET_LWIP)
++      } else {
+               ip_to_string(net_server_ip, tmp + strlen("http://"));
+ #endif
+       }
+       uridp_len = sizeof(struct efi_device_path) + strlen(tmp) + 1;
+       uridp = efi_alloc(uridp_len + sizeof(END));
+       if (!uridp) {
+               log_err("Out of memory\n");
+               return NULL;
+       }
+       uridp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
+       uridp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_URI;
+       uridp->dp.length = uridp_len;
+       debug("device path: setting uri device path to %s\n", tmp);
+       memcpy(uridp->uri, tmp, strlen(tmp) + 1);
+       pos = (char *)uridp + uridp_len;
+       memcpy(pos, &END, sizeof(END));
+       dp2 = efi_dp_concat(dp1, (const struct efi_device_path *)uridp, 0);
+       efi_free_pool(uridp);
+       efi_free_pool(dp1);
+       return dp2;
+ }
  /* Construct a device-path for memory-mapped image */
  struct efi_device_path *efi_dp_from_mem(uint32_t memory_type,
                                        uint64_t start_address,