blob: 9f51f77fa9a4fba867df6a4fb6f113389a357c71 [file] [log] [blame]
Adriano Cordova9debc902024-12-04 00:05:25 -03001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Implementation of EFI_IP4_CONFIG2_PROTOCOL
4 *
5 */
6
Heinrich Schuchardt955a3212025-01-16 20:26:59 +01007#define LOG_CATEGORY LOGC_EFI
8
Adriano Cordova9debc902024-12-04 00:05:25 -03009#include <efi_loader.h>
10#include <image.h>
11#include <malloc.h>
12#include <mapmem.h>
13#include <net.h>
14
15static const efi_guid_t efi_ip4_config2_guid = EFI_IP4_CONFIG2_PROTOCOL_GUID;
16
17struct efi_ip4_config2_manual_address current_http_ip;
18static enum efi_ip4_config2_policy current_policy;
19static char current_mac_addr[32];
20
21/* EFI_IP4_CONFIG2_PROTOCOL */
22
23/*
24 * efi_ip4_config2_set_data() - Set the configuration for the EFI IPv4 network
25 * stack running on the communication device
26 *
27 * This function implements EFI_IP4_CONFIG2_PROTOCOL.SetData()
28 * See the Unified Extensible Firmware Interface
29 * (UEFI) specification for details.
30 *
31 * @this: pointer to the protocol instance
32 * @data_type: the type of data to set
33 * @data_size: size of the buffer pointed to by data in bytes
34 * @data: the data buffer to set
35 * Return: status code
36 */
37static efi_status_t EFIAPI efi_ip4_config2_set_data(struct efi_ip4_config2_protocol *this,
38 enum efi_ip4_config2_data_type data_type,
39 efi_uintn_t data_size,
40 void *data)
41{
42 EFI_ENTRY("%p, %d, %zu, %p", this, data_type, data_size, data);
43 efi_status_t ret = EFI_SUCCESS;
44
45 if (!this || (data && !data_size) || (!data && data_size))
46 return EFI_EXIT(EFI_INVALID_PARAMETER);
47
48 switch (data_type) {
49 case EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO:
50 return EFI_EXIT(EFI_WRITE_PROTECTED);
51 case EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS:
52 if (current_policy != EFI_IP4_CONFIG2_POLICY_STATIC)
53 return EFI_EXIT(EFI_WRITE_PROTECTED);
54 if (!data_size && !data) {
55 memset((void *)&current_http_ip, 0,
56 sizeof(current_http_ip));
57 return EFI_EXIT(EFI_SUCCESS);
58 }
59 if (data && data_size == sizeof(struct efi_ip4_config2_manual_address)) {
60 memcpy((void *)&current_http_ip, data,
61 sizeof(struct efi_ip4_config2_manual_address));
62 efi_net_set_addr(&current_http_ip.address,
Adriano Cordova54674692025-03-03 11:13:15 -030063 &current_http_ip.subnet_mask, NULL, NULL);
Adriano Cordova9debc902024-12-04 00:05:25 -030064 return EFI_EXIT(EFI_SUCCESS);
65 }
66 return EFI_EXIT(EFI_BAD_BUFFER_SIZE);
67 case EFI_IP4_CONFIG2_DATA_TYPE_POLICY:
68 if (data && data_size == sizeof(enum efi_ip4_config2_policy)) {
69 current_policy = *(enum efi_ip4_config2_policy *)data;
70 return EFI_EXIT(EFI_SUCCESS);
71 }
72 return EFI_EXIT(EFI_BAD_BUFFER_SIZE);
73
74 default:
75 return EFI_EXIT(EFI_UNSUPPORTED);
76 }
77
78 return EFI_EXIT(ret);
79}
80
81/*
82 * efi_ip4_config2_get_data() - Get the configuration for the EFI IPv4 network
83 * stack running on the communication device
84 *
85 * This function implements EFI_IP4_CONFIG2_PROTOCOL.GetData()
86 * See the Unified Extensible Firmware Interface
87 * (UEFI) specification for details.
88 *
89 * @this: pointer to the protocol instance
90 * @data_type: the type of data to get
91 * @data_size: size
92 * @data: the data buffer
93 * Return: status code
94 */
95static efi_status_t EFIAPI efi_ip4_config2_get_data(struct efi_ip4_config2_protocol *this,
96 enum efi_ip4_config2_data_type data_type,
97 efi_uintn_t *data_size,
98 void *data)
99{
100 EFI_ENTRY("%p, %d, %p, %p", this, data_type, data_size, data);
101
102 efi_status_t ret = EFI_SUCCESS;
103 struct efi_ip4_config2_interface_info *info;
104 int tmp;
105
106 if (!this || !data_size)
107 return EFI_EXIT(EFI_INVALID_PARAMETER);
108
109 if (*data_size && !data)
110 return EFI_EXIT(EFI_INVALID_PARAMETER);
111
112 tmp = sizeof(struct efi_ip4_config2_interface_info) + sizeof(struct efi_ip4_route_table);
113
114 switch (data_type) {
115 case EFI_IP4_CONFIG2_DATA_TYPE_INTERFACEINFO:
116 if (*data_size < tmp) {
117 *data_size = tmp;
118 return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
119 }
120
121 info = (struct efi_ip4_config2_interface_info *)data;
122 memset(info, 0, sizeof(*info));
123
124 info->hw_address_size = 6;
125 memcpy(info->hw_address.mac_addr, current_mac_addr, 6);
126 // Set the route table size
127
128 info->route_table_size = 0;
129 break;
130 case EFI_IP4_CONFIG2_DATA_TYPE_MANUAL_ADDRESS:
131 if (*data_size < sizeof(struct efi_ip4_config2_manual_address)) {
132 *data_size = sizeof(struct efi_ip4_config2_manual_address);
133 return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
134 }
135
Adriano Cordova54674692025-03-03 11:13:15 -0300136 efi_net_get_addr(&current_http_ip.address, &current_http_ip.subnet_mask, NULL, NULL);
Adriano Cordova9debc902024-12-04 00:05:25 -0300137 memcpy(data, (void *)&current_http_ip,
138 sizeof(struct efi_ip4_config2_manual_address));
139
140 break;
141 default:
142 return EFI_EXIT(EFI_NOT_FOUND);
143 }
144 return EFI_EXIT(ret);
145}
146
147/*
148 * efi_ip4_config2_register_notify() - Register an event that is to be signaled whenever
149 * a configuration process on the specified configuration
150 * data is done
151 *
152 * This function implements EFI_IP4_CONFIG2_PROTOCOL.RegisterDataNotify()
153 * See the Unified Extensible Firmware Interface
154 * (UEFI) specification for details.
155 *
156 * @this: pointer to the protocol instance
157 * @data_type: the type of data to register the event for
158 * @event: the event to register
159 * Return: status code
160 */
161static efi_status_t EFIAPI efi_ip4_config2_register_notify(struct efi_ip4_config2_protocol *this,
162 enum efi_ip4_config2_data_type data_type,
163 struct efi_event *event)
164{
165 EFI_ENTRY("%p, %d, %p", this, data_type, event);
166
167 return EFI_EXIT(EFI_UNSUPPORTED);
168}
169
170/*
171 * efi_ip4_config2_unregister_notify() - Remove a previously registered eventfor
172 * the specified configuration data
173 *
174 * This function implements EFI_IP4_CONFIG2_PROTOCOL.UnregisterDataNotify()
175 * See the Unified Extensible Firmware Interface
176 * (UEFI) specification for details.
177 *
178 * @this: pointer to the protocol instance
179 * @data_type: the type of data to remove the event for
180 * @event: the event to unregister
181 * Return: status code
182 */
183static efi_status_t EFIAPI efi_ip4_config2_unregister_notify(struct efi_ip4_config2_protocol *this,
184 enum efi_ip4_config2_data_type data_type,
185 struct efi_event *event)
186{
187 EFI_ENTRY("%p, %d, %p", this, data_type, event);
188
189 return EFI_EXIT(EFI_UNSUPPORTED);
190}
191
192/**
193 * efi_ipconfig_register() - register the ip4_config2 protocol
194 *
195 */
196efi_status_t efi_ipconfig_register(const efi_handle_t handle,
197 struct efi_ip4_config2_protocol *ip4config)
198{
199 efi_status_t r = EFI_SUCCESS;
200
201 r = efi_add_protocol(handle, &efi_ip4_config2_guid,
202 ip4config);
203 if (r != EFI_SUCCESS) {
204 log_err("ERROR: Failure to add protocol\n");
205 return r;
206 }
207
208 memcpy(current_mac_addr, eth_get_ethaddr(), 6);
209
210 ip4config->set_data = efi_ip4_config2_set_data;
211 ip4config->get_data = efi_ip4_config2_get_data;
212 ip4config->register_data_notify = efi_ip4_config2_register_notify;
213 ip4config->unregister_data_notify = efi_ip4_config2_unregister_notify;
214
215 return EFI_SUCCESS;
216}