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