]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/SnpDxe/Station_address.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Station_address.c
1 /** @file
2 Implementation of reading the MAC address of a network adapter.
3
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "Snp.h"
10
11
12 /**
13 Call UNDI to read the MAC address of the NIC and update the mode structure
14 with the address.
15
16 @param Snp Pointer to snp driver structure.
17
18 @retval EFI_SUCCESS The MAC address of the NIC is read successfully.
19 @retval EFI_DEVICE_ERROR Failed to read the MAC address of the NIC.
20
21 **/
22 EFI_STATUS
23 PxeGetStnAddr (
24 SNP_DRIVER *Snp
25 )
26 {
27 PXE_DB_STATION_ADDRESS *Db;
28
29 Db = Snp->Db;
30 Snp->Cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
31 Snp->Cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ;
32
33 Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
34 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
35
36 Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_STATION_ADDRESS);
37 Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
38
39 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
40 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
41 Snp->Cdb.IFnum = Snp->IfNum;
42 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
43
44 //
45 // Issue UNDI command and check result.
46 //
47 DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
48
49 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
50
51 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
52 DEBUG (
53 (EFI_D_ERROR,
54 "\nsnp->undi.station_addr() %xh:%xh\n",
55 Snp->Cdb.StatFlags,
56 Snp->Cdb.StatCode)
57 );
58
59 return EFI_DEVICE_ERROR;
60 }
61 //
62 // Set new station address in SNP->Mode structure and return success.
63 //
64 CopyMem (
65 &(Snp->Mode.CurrentAddress),
66 &Db->StationAddr,
67 Snp->Mode.HwAddressSize
68 );
69
70 CopyMem (
71 &Snp->Mode.BroadcastAddress,
72 &Db->BroadcastAddr,
73 Snp->Mode.HwAddressSize
74 );
75
76 CopyMem (
77 &Snp->Mode.PermanentAddress,
78 &Db->PermanentAddr,
79 Snp->Mode.HwAddressSize
80 );
81
82 return EFI_SUCCESS;
83 }
84
85
86 /**
87 Call UNDI to set a new MAC address for the NIC.
88
89 @param Snp Pointer to Snp driver structure.
90 @param NewMacAddr Pointer to a MAC address to be set for the NIC, if this is
91 NULL then this routine resets the mac address to the NIC's
92 original address.
93
94
95 **/
96 EFI_STATUS
97 PxeSetStnAddr (
98 SNP_DRIVER *Snp,
99 EFI_MAC_ADDRESS *NewMacAddr
100 )
101 {
102 PXE_CPB_STATION_ADDRESS *Cpb;
103 PXE_DB_STATION_ADDRESS *Db;
104
105 Cpb = Snp->Cpb;
106 Db = Snp->Db;
107 Snp->Cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
108
109 if (NewMacAddr == NULL) {
110 Snp->Cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_RESET;
111 Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
112 Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
113 } else {
114 Snp->Cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_WRITE;
115 //
116 // Supplying a new address in the CPB will make undi change the mac address to the new one.
117 //
118 CopyMem (&Cpb->StationAddr, NewMacAddr, Snp->Mode.HwAddressSize);
119
120 Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_STATION_ADDRESS);
121 Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;
122 }
123
124 Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_STATION_ADDRESS);
125 Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
126
127 Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
128 Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
129 Snp->Cdb.IFnum = Snp->IfNum;
130 Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
131
132 //
133 // Issue UNDI command and check result.
134 //
135 DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
136
137 (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
138
139 if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
140 DEBUG (
141 (EFI_D_ERROR,
142 "\nsnp->undi.station_addr() %xh:%xh\n",
143 Snp->Cdb.StatFlags,
144 Snp->Cdb.StatCode)
145 );
146
147 //
148 // UNDI command failed. Return UNDI status to caller.
149 //
150 return EFI_DEVICE_ERROR;
151 }
152 //
153 // read the changed address and save it in SNP->Mode structure
154 //
155 PxeGetStnAddr (Snp);
156
157 return EFI_SUCCESS;
158 }
159
160
161 /**
162 Modifies or resets the current station address, if supported.
163
164 This function modifies or resets the current station address of a network
165 interface, if supported. If Reset is TRUE, then the current station address is
166 set to the network interface's permanent address. If Reset is FALSE, and the
167 network interface allows its station address to be modified, then the current
168 station address is changed to the address specified by New. If the network
169 interface does not allow its station address to be modified, then
170 EFI_INVALID_PARAMETER will be returned. If the station address is successfully
171 updated on the network interface, EFI_SUCCESS will be returned. If the driver
172 has not been initialized, EFI_DEVICE_ERROR will be returned.
173
174 @param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
175 @param Reset Flag used to reset the station address to the network interface's
176 permanent address.
177 @param New New station address to be used for the network interface.
178
179
180 @retval EFI_SUCCESS The network interface's station address was updated.
181 @retval EFI_NOT_STARTED The Simple Network Protocol interface has not been
182 started by calling Start().
183 @retval EFI_INVALID_PARAMETER The New station address was not accepted by the NIC.
184 @retval EFI_INVALID_PARAMETER Reset is FALSE and New is NULL.
185 @retval EFI_DEVICE_ERROR The Simple Network Protocol interface has not
186 been initialized by calling Initialize().
187 @retval EFI_DEVICE_ERROR An error occurred attempting to set the new
188 station address.
189 @retval EFI_UNSUPPORTED The NIC does not support changing the network
190 interface's station address.
191
192 **/
193 EFI_STATUS
194 EFIAPI
195 SnpUndi32StationAddress (
196 IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
197 IN BOOLEAN Reset,
198 IN EFI_MAC_ADDRESS *New OPTIONAL
199 )
200 {
201 SNP_DRIVER *Snp;
202 EFI_STATUS Status;
203 EFI_TPL OldTpl;
204
205 //
206 // Check for invalid parameter combinations.
207 //
208 if ((This == NULL) ||
209 (!Reset && (New == NULL))) {
210 return EFI_INVALID_PARAMETER;
211 }
212
213 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
214
215 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
216
217 //
218 // Return error if the SNP is not initialized.
219 //
220 switch (Snp->Mode.State) {
221 case EfiSimpleNetworkInitialized:
222 break;
223
224 case EfiSimpleNetworkStopped:
225 Status = EFI_NOT_STARTED;
226 goto ON_EXIT;
227
228 default:
229 Status = EFI_DEVICE_ERROR;
230 goto ON_EXIT;
231 }
232
233 if (Reset) {
234 Status = PxeSetStnAddr (Snp, NULL);
235 } else {
236 Status = PxeSetStnAddr (Snp, New);
237 }
238
239 ON_EXIT:
240 gBS->RestoreTPL (OldTpl);
241
242 return Status;
243 }