summaryrefslogtreecommitdiff
path: root/lib/efi_selftest/efi_selftest_ipconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/efi_selftest/efi_selftest_ipconfig.c')
-rw-r--r--lib/efi_selftest/efi_selftest_ipconfig.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/lib/efi_selftest/efi_selftest_ipconfig.c b/lib/efi_selftest/efi_selftest_ipconfig.c
new file mode 100644
index 00000000000..8d594f5e193
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_ipconfig.c
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * efi_selftest_ipconfig
+ *
+ * This unit test covers the IPv4 Config2 Protocol.
+ *
+ */
+
+#include <efi_selftest.h>
+#include <charset.h>
+#include <net.h>
+
+static struct efi_boot_services *boottime;
+
+static struct efi_ip4_config2_protocol *ip4_config2;
+static const efi_guid_t efi_ip4_config2_guid = EFI_IP4_CONFIG2_PROTOCOL_GUID;
+
+/*
+ * Setup unit test.
+ *
+ * Open IPv4 Config2 protocol
+ *
+ * @handle: handle of the loaded image
+ * @systable: system table
+ * Return: EFI_ST_SUCCESS for success
+ */
+static int setup(const efi_handle_t handle,
+ const struct efi_system_table *systable)
+{
+ efi_status_t ret;
+ efi_handle_t *net_handle;
+ efi_uintn_t num_handles;
+ efi_handle_t *handles;
+
+ boottime = systable->boottime;
+
+ num_handles = 0;
+ boottime->locate_handle_buffer(BY_PROTOCOL, &efi_ip4_config2_guid,
+ NULL, &num_handles, &handles);
+
+ if (!num_handles) {
+ efi_st_error("Failed to locate ipv4 config2 protocol\n");
+ return EFI_ST_FAILURE;
+ }
+
+ for (net_handle = handles; num_handles--; net_handle++) {
+ ret = boottime->open_protocol(*net_handle, &efi_ip4_config2_guid,
+ (void **)&ip4_config2, 0, 0,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS || !ip4_config2)
+ continue;
+ break; // Get first handle that supports ipv4
+ }
+
+ if (!ip4_config2) {
+ efi_st_error("Failed to open ipv4 config2 protocol\n");
+ return EFI_ST_FAILURE;
+ }
+
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Execute unit test.
+ *
+ *
+ * Return: EFI_ST_SUCCESS for success
+ */
+static int execute(void)
+{
+ efi_status_t ret;
+ enum efi_ip4_config2_policy policy;
+ efi_uintn_t data_size;
+ struct efi_ip4_config2_manual_address manual_address;
+ struct efi_ip4_config2_manual_address orig_address;
+ u8 netmask[] = {255, 255, 255, 0};
+ u8 ip[] = {10, 0, 0, 1};
+
+ /* Setup may have failed */
+ if (!ip4_config2) {
+ efi_st_error("Setup failure, cannot proceed with test\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Set policy to static */
+ policy = EFI_IP4_CONFIG2_POLICY_STATIC;
+ ret = ip4_config2->set_data(ip4_config2, EFI_IP4_CONFIG2_DATA_TYPE_POLICY,
+ sizeof(policy), (void *)&policy);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to set policy\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Save original ip address and netmask */
+ data_size = sizeof(manual_address);
+ ret = ip4_config2->get_data(ip4_config2, EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
+ &data_size, &orig_address);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to save original ip address and netmask\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Set static ip and netmask */
+ memcpy(&manual_address.address, ip,
+ sizeof(struct efi_ipv4_address));
+ memcpy(&manual_address.subnet_mask, netmask,
+ sizeof(struct efi_ipv4_address));
+ ret = ip4_config2->set_data(ip4_config2, EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
+ sizeof(manual_address), &manual_address);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to get ip address and netmask\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Try to set interface info, this should fail */
+ ret = ip4_config2->set_data(ip4_config2, EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO, 0, NULL);
+ if (ret == EFI_SUCCESS) {
+ efi_st_error("Interface info is read-only\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Get ip address and netmask and check that they match with the previously set ones */
+ data_size = sizeof(manual_address);
+ ret = ip4_config2->get_data(ip4_config2, EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
+ &data_size, &manual_address);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to get ip address and netmask\n");
+ return EFI_ST_FAILURE;
+ }
+ if (memcmp(ip, &manual_address.address,
+ sizeof(struct efi_ipv4_address)) ||
+ memcmp(netmask, &manual_address.subnet_mask,
+ sizeof(struct efi_ipv4_address))) {
+ efi_st_error("Ip address mismatch\n");
+ return EFI_ST_FAILURE;
+ }
+
+ /* Restore original ip address and netmask */
+ ret = ip4_config2->set_data(ip4_config2, EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS,
+ sizeof(orig_address), &orig_address);
+ if (ret != EFI_SUCCESS) {
+ efi_st_error("Failed to restore original ip address and netmask\n");
+ return EFI_ST_FAILURE;
+ }
+
+ efi_st_printf("Efi ipconfig test execute succeeded\n");
+ return EFI_ST_SUCCESS;
+}
+
+/*
+ * Tear down unit test.
+ *
+ * Return: EFI_ST_SUCCESS for success
+ */
+static int teardown(void)
+{
+ int exit_status = EFI_ST_SUCCESS;
+
+ return exit_status;
+}
+
+EFI_UNIT_TEST(ipconfig) = {
+ .name = "IPv4 config2 protocol",
+ .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
+ .setup = setup,
+ .execute = execute,
+ .teardown = teardown,
+#ifdef CONFIG_SANDBOX
+ /*
+ * Running this test on the sandbox requires setting environment
+ * variable ethact to a network interface connected to a DHCP server and
+ * ethrotate to 'no'.
+ */
+ .on_request = true,
+#endif
+};