]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiIbft.c
1)update function header coding style issue
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiIbft.c
1 /** @file
2 Implementation for iSCSI Boot Firmware Table publication.
3
4 Copyright (c) 2004 - 2008, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which 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 "IScsiImpl.h"
16
17 /**
18 Initialize the header of the iSCSI Boot Firmware Table.
19
20 @param[in] Header The header of the iSCSI Boot Firmware Table.
21 **/
22 VOID
23 IScsiInitIbfTableHeader (
24 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header
25 )
26 {
27 ZeroMem (Header, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER));
28
29 Header->Signature = EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE;
30 Header->Length = IBFT_HEAP_OFFSET;
31 Header->Revision = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;
32 Header->Checksum = 0;
33
34 Header->OemId[0] = 'I';
35 Header->OemId[1] = 'N';
36 Header->OemId[2] = 'T';
37 Header->OemId[3] = 'E';
38 Header->OemId[4] = 'L';
39 }
40
41 /**
42 Initialize the control section of the iSCSI Boot Firmware Table.
43
44 @param[in] Table The ACPI table.
45 @param[in] HandleCount The number of the handles associated with iSCSI sessions, it's
46 equal to the number of iSCSI sessions.
47 **/
48 VOID
49 IScsiInitControlSection (
50 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
51 IN UINTN HandleCount
52 )
53 {
54 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
55 UINTN NumOffset;
56
57 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
58
59 ZeroMem (Control, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE));
60
61 Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;
62 Control->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;
63 Control->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);
64
65 //
66 // Each session occupies two offsets, one for the NIC section,
67 // the other for the Target section.
68 //
69 NumOffset = 2 * HandleCount;
70 if (NumOffset > 4) {
71 //
72 // Need expand the control section if more than 2 NIC/Target sections
73 // exist.
74 //
75 Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));
76 }
77 }
78
79 /**
80 Add one item into the heap.
81
82 @param[in, out] Heap On input, the current address of the heap; On output, the address of
83 the heap after the item is added.
84 @param[in] Data The data to add into the heap.
85 @param[in] Len Length of the Data in byte.
86 **/
87 VOID
88 IScsiAddHeapItem (
89 IN OUT UINT8 **Heap,
90 IN VOID *Data,
91 IN UINTN Len
92 )
93 {
94 //
95 // Add one byte for the NULL delimiter.
96 //
97 *Heap -= Len + 1;
98
99 CopyMem (*Heap, Data, Len);
100 *(*Heap + Len) = 0;
101 }
102
103 /**
104 Fill the Initiator section of the iSCSI Boot Firmware Table.
105
106 @param[in] Table The ACPI table.
107 @param[in, out] Heap The heap.
108 @param[in] Handle The handle associated with the iSCSI session.
109 **/
110 VOID
111 IScsiFillInitiatorSection (
112 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
113 IN OUT UINT8 **Heap,
114 IN EFI_HANDLE Handle
115 )
116 {
117 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
118 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *Initiator;
119 ISCSI_DRIVER_DATA *DriverData;
120 ISCSI_SESSION *Session;
121 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
122 EFI_STATUS Status;
123
124 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
125
126 //
127 // Initiator section immediately follows the control section.
128 //
129 Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *) ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));
130
131 Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);
132
133 ZeroMem (Initiator, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE));
134
135 Initiator->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID;
136 Initiator->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION;
137 Initiator->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);
138 Initiator->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BLOCK_VALID | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED;
139
140 //
141 // Get the identifier from the handle.
142 //
143 Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, (VOID **) &IScsiIdentifier);
144 if (EFI_ERROR (Status)) {
145 ASSERT (FALSE);
146 return ;
147 }
148
149 DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
150 Session = &DriverData->Session;
151
152 //
153 // Fill the iSCSI Initiator Name into the heap.
154 //
155 IScsiAddHeapItem (Heap, Session->InitiatorName, Session->InitiatorNameLength - 1);
156
157 Initiator->IScsiNameLength = (UINT16) (Session->InitiatorNameLength - 1);
158 Initiator->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
159 }
160
161 /**
162 Map the v4 IP address into v6 IP address.
163
164 @param[in] V4 The v4 IP address.
165 @param[out] V6 The v6 IP address.
166 **/
167 VOID
168 IScsiMapV4ToV6Addr (
169 IN EFI_IPv4_ADDRESS *V4,
170 OUT EFI_IPv6_ADDRESS *V6
171 )
172 {
173 UINTN Index;
174
175 ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));
176
177 V6->Addr[10] = 0xff;
178 V6->Addr[11] = 0xff;
179
180 for (Index = 0; Index < 4; Index++) {
181 V6->Addr[12 + Index] = V4->Addr[Index];
182 }
183 }
184
185 /**
186 Get the NIC's PCI location and return it accroding to the composited
187 format defined in iSCSI Boot Firmware Table.
188
189 @param[in] Controller The handle of the controller.
190
191 @return UINT16 The composited representation of the NIC PCI location.
192 @retval 0 Other errors as indicated.
193 **/
194 UINT16
195 IScsiGetNICPciLocation (
196 IN EFI_HANDLE Controller
197 )
198 {
199 EFI_STATUS Status;
200 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
201 EFI_HANDLE PciIoHandle;
202 EFI_PCI_IO_PROTOCOL *PciIo;
203 UINTN Segment;
204 UINTN Bus;
205 UINTN Device;
206 UINTN Function;
207
208 Status = gBS->HandleProtocol (
209 Controller,
210 &gEfiDevicePathProtocolGuid,
211 (VOID **)&DevicePath
212 );
213 if (EFI_ERROR (Status)) {
214 return 0;
215 }
216
217 Status = gBS->LocateDevicePath (
218 &gEfiPciIoProtocolGuid,
219 &DevicePath,
220 &PciIoHandle
221 );
222 if (EFI_ERROR (Status)) {
223 return 0;
224 }
225
226 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);
227 if (EFI_ERROR (Status)) {
228 return 0;
229 }
230
231 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
232 if (EFI_ERROR (Status)) {
233 return 0;
234 }
235
236 return (UINT16) ((Bus << 8) | (Device << 3) | Function);
237 }
238
239 /**
240 Get the MAC address of the controller.
241
242 @param[in] Controller The handle of the controller.
243
244 @return EFI_MAC_ADDRESS * The mac address.
245 **/
246 EFI_MAC_ADDRESS *
247 IScsiGetMacAddress (
248 IN EFI_HANDLE Controller
249 )
250 {
251 EFI_STATUS Status;
252 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
253
254 Status = gBS->HandleProtocol (
255 Controller,
256 &gEfiSimpleNetworkProtocolGuid,
257 (VOID **) &Snp
258 );
259 ASSERT_EFI_ERROR (Status);
260
261 return &Snp->Mode->PermanentAddress;
262 }
263
264 /**
265 Fill the NIC and target sections in iSCSI Boot Firmware Table.
266
267 @param[in] Table The buffer of the ACPI table.
268 @param[in, out] Heap The heap buffer used to store the variable length parameters such as iSCSI name.
269 @param[in] HandleCount Count The number of handles having iSCSI private protocol installed.
270 @param[in] Handles The handle buffer.
271 **/
272 VOID
273 IScsiFillNICAndTargetSections (
274 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
275 IN OUT UINT8 **Heap,
276 IN UINTN HandleCount,
277 IN EFI_HANDLE *Handles
278 )
279 {
280 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
281 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *Nic;
282 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *Target;
283 ISCSI_DRIVER_DATA *DriverData;
284 ISCSI_SESSION_CONFIG_DATA *SessionConfigData;
285 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;
286 UINT16 *SectionOffset;
287 UINTN Index;
288 UINT16 Length;
289 EFI_MAC_ADDRESS *Mac;
290 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
291 EFI_STATUS Status;
292
293 //
294 // Get the offset of the first Nic and Target section.
295 //
296 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
297 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +
298 Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));
299 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
300 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
301
302 SectionOffset = &Control->NIC0Offset;
303
304 for (Index = 0; Index < HandleCount; Index++) {
305 Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, (VOID **)&IScsiIdentifier);
306 if (EFI_ERROR (Status)) {
307 ASSERT (FALSE);
308 return ;
309 }
310
311 DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
312 SessionConfigData = &DriverData->Session.ConfigData;
313 AuthConfig = &DriverData->Session.AuthData.AuthConfig;
314
315 //
316 // Fill the Nic section.
317 //
318 ZeroMem (Nic, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE));
319
320 Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;
321 Nic->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;
322 Nic->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);
323 Nic->Header.Index = (UINT8) Index;
324 Nic->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |
325 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED |
326 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;
327
328 //
329 // Get the subnet mask prefix length.
330 //
331 Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&SessionConfigData->NvData.SubnetMask);
332
333 if (SessionConfigData->NvData.InitiatorInfoFromDhcp) {
334 Nic->Origin = IpPrefixOriginDhcp;
335 } else {
336 Nic->Origin = IpPrefixOriginManual;
337 }
338 //
339 // Map the various v4 addresses into v6 addresses.
340 //
341 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.LocalIp, &Nic->Ip);
342 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.Gateway, &Nic->Gateway);
343 IScsiMapV4ToV6Addr (&SessionConfigData->PrimaryDns, &Nic->PrimaryDns);
344 IScsiMapV4ToV6Addr (&SessionConfigData->SecondaryDns, &Nic->SecondaryDns);
345 IScsiMapV4ToV6Addr (&SessionConfigData->DhcpServer, &Nic->DhcpServer);
346
347 Mac = IScsiGetMacAddress (DriverData->Controller);
348 CopyMem (Nic->Mac, Mac, sizeof (Nic->Mac));
349
350 //
351 // Get the PCI location of the Nic.
352 //
353 Nic->PciLocation = IScsiGetNICPciLocation (DriverData->Controller);
354
355 *SectionOffset = (UINT16) ((UINTN) Nic - (UINTN) Table);
356 SectionOffset++;
357
358 //
359 // Fill the Target section.
360 //
361 ZeroMem (Target, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE));
362
363 Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;
364 Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;
365 Target->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);
366 Target->Header.Index = (UINT8) Index;
367 Target->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;
368 Target->Port = SessionConfigData->NvData.TargetPort;
369 Target->CHAPType = AuthConfig->CHAPType;
370 Target->NicIndex = (UINT8) Index;
371
372 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.TargetIp, &Target->Ip);
373 CopyMem (Target->BootLun, SessionConfigData->NvData.BootLun, sizeof (Target->BootLun));
374
375 //
376 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
377 //
378 Length = (UINT16) AsciiStrLen (SessionConfigData->NvData.TargetName);
379 IScsiAddHeapItem (Heap, SessionConfigData->NvData.TargetName, Length);
380
381 Target->IScsiNameLength = Length;
382 Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
383
384 if (Target->CHAPType != ISCSI_CHAP_NONE) {
385 //
386 // CHAP Name
387 //
388 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);
389 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);
390 Target->CHAPNameLength = Length;
391 Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
392
393 //
394 // CHAP Secret
395 //
396 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);
397 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);
398 Target->CHAPSecretLength = Length;
399 Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
400
401 if (Target->CHAPType == ISCSI_CHAP_MUTUAL) {
402 //
403 // Reverse CHAP Name
404 //
405 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);
406 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);
407 Target->ReverseCHAPNameLength = Length;
408 Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
409
410 //
411 // Reverse CHAP Secret
412 //
413 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);
414 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);
415 Target->ReverseCHAPSecretLength = Length;
416 Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
417 }
418 }
419
420 *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);
421 SectionOffset++;
422
423 //
424 // Advance to the next NIC/Target pair
425 //
426 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +
427 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));
428 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
429 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
430 }
431 }
432
433 /**
434 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
435 session status.
436 **/
437 VOID
438 IScsiPublishIbft (
439 VOID
440 )
441 {
442 EFI_STATUS Status;
443 UINTN TableHandle;
444 EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
445 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;
446 UINTN HandleCount;
447 EFI_HANDLE *HandleBuffer;
448 UINT8 *Heap;
449 INTN Index;
450 EFI_ACPI_TABLE_VERSION Version;
451 UINT32 Signature;
452
453 Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (VOID **)&AcpiSupport);
454 if (EFI_ERROR (Status)) {
455 return ;
456 }
457 //
458 // Try to remove the old iSCSI Boot Firmware Table.
459 //
460 for (Index = 0;; Index++) {
461 Status = AcpiSupport->GetAcpiTable (
462 AcpiSupport,
463 Index,
464 (VOID **)&Table,
465 &Version,
466 &TableHandle
467 );
468 if (EFI_ERROR (Status)) {
469 break;
470 }
471
472 Signature = Table->Signature;
473 gBS->FreePool (Table);
474
475 if (Signature == EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE) {
476 //
477 // Remove the table.
478 //
479 Status = AcpiSupport->SetAcpiTable (
480 AcpiSupport,
481 NULL,
482 FALSE,
483 Version,
484 &TableHandle
485 );
486 if (EFI_ERROR (Status)) {
487 return ;
488 }
489
490 break;
491 }
492 }
493 //
494 // Get all iSCSI private protocols.
495 //
496 Status = gBS->LocateHandleBuffer (
497 ByProtocol,
498 &mIScsiPrivateGuid,
499 NULL,
500 &HandleCount,
501 &HandleBuffer
502 );
503 if (EFI_ERROR (Status)) {
504 return ;
505 }
506 //
507 // Allocate 4k bytes to hold the ACPI table.
508 //
509 Table = AllocatePool (IBFT_MAX_SIZE);
510 if (Table == NULL) {
511 return ;
512 }
513
514 Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;
515
516 //
517 // Fill in the various section of the iSCSI Boot Firmware Table.
518 //
519 IScsiInitIbfTableHeader (Table);
520 IScsiInitControlSection (Table, HandleCount);
521 IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]);
522 IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer);
523
524 gBS->FreePool (HandleBuffer);
525
526 TableHandle = 0;
527
528 //
529 // Install or update the iBFT table.
530 //
531 Status = AcpiSupport->SetAcpiTable (
532 AcpiSupport,
533 Table,
534 TRUE,
535 EFI_ACPI_TABLE_VERSION_3_0,
536 &TableHandle
537 );
538 if (!EFI_ERROR (Status)) {
539 AcpiSupport->PublishTables (AcpiSupport, EFI_ACPI_TABLE_VERSION_3_0);
540 }
541
542 gBS->FreePool (Table);
543 }