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