3 Copyright (c) 2007 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
18 Implementation for iSCSI Boot Firmware Table publication.
22 #include "IScsiImpl.h"
26 IScsiInitIbfTableHeader (
27 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Header
33 Initialize the header of the iSCSI Boot Firmware Table.
37 Header - The header of the iSCSI Boot Firmware Table.
45 NetZeroMem (Header
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
));
47 Header
->Signature
= EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE
;
48 Header
->Length
= IBFT_HEAP_OFFSET
;
49 Header
->Revision
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION
;
52 Header
->OemId
[0] = 'I';
53 Header
->OemId
[1] = 'N';
54 Header
->OemId
[2] = 'T';
55 Header
->OemId
[3] = 'E';
56 Header
->OemId
[4] = 'L';
61 IScsiInitControlSection (
62 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
,
69 Initialize the control section of the iSCSI Boot Firmware Table.
73 Table - The ACPI table.
74 HandleCount - The number of the handles associated with iSCSI sessions, it's
75 equal to the number of iSCSI sessions.
83 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*Control
;
86 Control
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*) (Table
+ 1);
88 NetZeroMem (Control
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
));
90 Control
->Header
.StructureId
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID
;
91 Control
->Header
.Version
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION
;
92 Control
->Header
.Length
= sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
);
95 // Each session occupies two offsets, one for the NIC section,
96 // the other for the Target section.
98 NumOffset
= 2 * HandleCount
;
101 // Need expand the control section if more than 2 NIC/Target sections
104 Control
->Header
.Length
= (UINT16
)(Control
->Header
.Length
+ (NumOffset
- 4) * sizeof (UINT16
));
119 Add one item into the heap.
123 Heap - On input, the current address of the heap; On output, the address of
124 the heap after the item is added.
125 Data - The data to add into the heap.
126 Len - Length of the Data in byte.
135 // Add one byte for the NULL delimiter.
139 NetCopyMem (*Heap
, Data
, Len
);
145 IScsiFillInitiatorSection (
146 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
,
154 Fill the Initiator section of the iSCSI Boot Firmware Table.
158 Table - The ACPI table.
160 Handle - The handle associated with the iSCSI session.
168 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*Control
;
169 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE
*Initiator
;
170 ISCSI_DRIVER_DATA
*DriverData
;
171 ISCSI_SESSION
*Session
;
172 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
175 Control
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*) (Table
+ 1);
178 // Initiator section immediately follows the control section.
180 Initiator
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE
*) ((UINT8
*) Control
+ IBFT_ROUNDUP (Control
->Header
.Length
));
182 Control
->InitiatorOffset
= (UINT16
) ((UINTN
) Initiator
- (UINTN
) Table
);
184 NetZeroMem (Initiator
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE
));
186 Initiator
->Header
.StructureId
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID
;
187 Initiator
->Header
.Version
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION
;
188 Initiator
->Header
.Length
= sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE
);
189 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
;
192 // Get the identifier from the handle.
194 Status
= gBS
->HandleProtocol (Handle
, &mIScsiPrivateGuid
, (void **)&IScsiIdentifier
);
195 if (EFI_ERROR (Status
)) {
200 DriverData
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
201 Session
= &DriverData
->Session
;
204 // Fill the iSCSI Initiator Name into the heap.
206 IScsiAddHeapItem (Heap
, Session
->InitiatorName
, Session
->InitiatorNameLength
- 1);
208 Initiator
->IScsiNameLength
= (UINT16
) (Session
->InitiatorNameLength
- 1);
209 Initiator
->IScsiNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
215 IN EFI_IPv4_ADDRESS
*V4
,
216 OUT EFI_IPv6_ADDRESS
*V6
222 Map the v4 IP address into v6 IP address.
226 V4 - The v4 IP address.
227 V6 - The v6 IP address.
237 NetZeroMem (V6
, sizeof (EFI_IPv6_ADDRESS
));
242 for (Index
= 0; Index
< 4; Index
++) {
243 V6
->Addr
[12 + Index
] = V4
->Addr
[Index
];
249 IScsiGetNICPciLocation (
250 IN EFI_HANDLE Controller
256 Get the NIC's PCI location and return it accroding to the composited
257 format defined in iSCSI Boot Firmware Table.
261 Controller - The handle of the controller.
265 UINT16 - The composited representation of the NIC PCI location.
270 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
271 EFI_HANDLE PciIoHandle
;
272 EFI_PCI_IO_PROTOCOL
*PciIo
;
278 Status
= gBS
->HandleProtocol (
280 &gEfiDevicePathProtocolGuid
,
283 if (EFI_ERROR (Status
)) {
287 Status
= gBS
->LocateDevicePath (
288 &gEfiPciIoProtocolGuid
,
292 if (EFI_ERROR (Status
)) {
296 Status
= gBS
->HandleProtocol (PciIoHandle
, &gEfiPciIoProtocolGuid
, (void **)&PciIo
);
297 if (EFI_ERROR (Status
)) {
301 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
302 if (EFI_ERROR (Status
)) {
306 return (UINT16
) ((Bus
<< 8) | (Device
<< 3) | Function
);
312 IN EFI_HANDLE Controller
318 Get the MAC address of the controller.
322 Controller - The handle of the controller.
326 EFI_MAC_ADDRESS * - The mac address.
331 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
333 Status
= gBS
->HandleProtocol (
335 &gEfiSimpleNetworkProtocolGuid
,
338 ASSERT_EFI_ERROR (Status
);
340 return &Snp
->Mode
->PermanentAddress
;
345 IScsiFillNICAndTargetSections (
346 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
,
348 IN UINTN HandleCount
,
349 IN EFI_HANDLE
*Handles
355 Fill the NIC and target sections in iSCSI Boot Firmware Table.
359 Table - The buffer of the ACPI table.
360 Heap - The heap buffer used to store the variable length parameters such as iSCSI name.
361 HandleCount - The number of handles having iSCSI private protocol installed.
362 Handles - The handle buffer.
370 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*Control
;
371 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
*Nic
;
372 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE
*Target
;
373 ISCSI_DRIVER_DATA
*DriverData
;
374 ISCSI_SESSION_CONFIG_DATA
*SessionConfigData
;
375 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfig
;
376 UINT16
*SectionOffset
;
379 EFI_MAC_ADDRESS
*Mac
;
380 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
384 // Get the offset of the first Nic and Target section.
386 Control
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*) (Table
+ 1);
387 Nic
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
*) ((UINTN
) Table
+
388 Control
->InitiatorOffset
+ IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE
)));
389 Target
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE
*) ((UINTN
) Nic
+
390 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
)));
392 SectionOffset
= &Control
->NIC0Offset
;
394 for (Index
= 0; Index
< HandleCount
; Index
++) {
395 Status
= gBS
->HandleProtocol (Handles
[Index
], &mIScsiPrivateGuid
, (void **)&IScsiIdentifier
);
396 if (EFI_ERROR (Status
)) {
401 DriverData
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
402 SessionConfigData
= &DriverData
->Session
.ConfigData
;
403 AuthConfig
= &DriverData
->Session
.AuthData
.AuthConfig
;
406 // Fill the Nic section.
408 NetZeroMem (Nic
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
));
410 Nic
->Header
.StructureId
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID
;
411 Nic
->Header
.Version
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION
;
412 Nic
->Header
.Length
= sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
);
413 Nic
->Header
.Index
= (UINT8
) Index
;
414 Nic
->Header
.Flags
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID
|
415 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED
|
416 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL
;
419 // Get the subnet mask prefix length.
421 Nic
->SubnetMaskPrefixLength
= IScsiGetSubnetMaskPrefixLength (&SessionConfigData
->NvData
.SubnetMask
);
423 if (SessionConfigData
->NvData
.InitiatorInfoFromDhcp
) {
424 Nic
->Origin
= IpPrefixOriginDhcp
;
426 Nic
->Origin
= IpPrefixOriginManual
;
429 // Map the various v4 addresses into v6 addresses.
431 IScsiMapV4ToV6Addr (&SessionConfigData
->NvData
.LocalIp
, &Nic
->Ip
);
432 IScsiMapV4ToV6Addr (&SessionConfigData
->NvData
.Gateway
, &Nic
->Gateway
);
433 IScsiMapV4ToV6Addr (&SessionConfigData
->PrimaryDns
, &Nic
->PrimaryDns
);
434 IScsiMapV4ToV6Addr (&SessionConfigData
->SecondaryDns
, &Nic
->SecondaryDns
);
435 IScsiMapV4ToV6Addr (&SessionConfigData
->DhcpServer
, &Nic
->DhcpServer
);
437 Mac
= IScsiGetMacAddress (DriverData
->Controller
);
438 NetCopyMem (Nic
->Mac
, Mac
, sizeof (Nic
->Mac
));
441 // Get the PCI location of the Nic.
443 Nic
->PciLocation
= IScsiGetNICPciLocation (DriverData
->Controller
);
445 *SectionOffset
= (UINT16
) ((UINTN
) Nic
- (UINTN
) Table
);
449 // Fill the Target section.
451 NetZeroMem (Target
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE
));
453 Target
->Header
.StructureId
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID
;
454 Target
->Header
.Version
= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION
;
455 Target
->Header
.Length
= sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE
);
456 Target
->Header
.Index
= (UINT8
) Index
;
457 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
;
458 Target
->Port
= SessionConfigData
->NvData
.TargetPort
;
459 Target
->CHAPType
= AuthConfig
->CHAPType
;
460 Target
->NicIndex
= (UINT8
) Index
;
462 IScsiMapV4ToV6Addr (&SessionConfigData
->NvData
.TargetIp
, &Target
->Ip
);
463 NetCopyMem (Target
->BootLun
, SessionConfigData
->NvData
.BootLun
, sizeof (Target
->BootLun
));
466 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
468 Length
= (UINT16
) AsciiStrLen (SessionConfigData
->NvData
.TargetName
);
469 IScsiAddHeapItem (Heap
, SessionConfigData
->NvData
.TargetName
, Length
);
471 Target
->IScsiNameLength
= Length
;
472 Target
->IScsiNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
474 if (Target
->CHAPType
!= ISCSI_CHAP_NONE
) {
478 Length
= (UINT16
) AsciiStrLen (AuthConfig
->CHAPName
);
479 IScsiAddHeapItem (Heap
, AuthConfig
->CHAPName
, Length
);
480 Target
->CHAPNameLength
= Length
;
481 Target
->CHAPNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
486 Length
= (UINT16
) AsciiStrLen (AuthConfig
->CHAPSecret
);
487 IScsiAddHeapItem (Heap
, AuthConfig
->CHAPSecret
, Length
);
488 Target
->CHAPSecretLength
= Length
;
489 Target
->CHAPSecretOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
491 if (Target
->CHAPType
== ISCSI_CHAP_MUTUAL
) {
495 Length
= (UINT16
) AsciiStrLen (AuthConfig
->ReverseCHAPName
);
496 IScsiAddHeapItem (Heap
, AuthConfig
->ReverseCHAPName
, Length
);
497 Target
->ReverseCHAPNameLength
= Length
;
498 Target
->ReverseCHAPNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
501 // Reverse CHAP Secret
503 Length
= (UINT16
) AsciiStrLen (AuthConfig
->ReverseCHAPSecret
);
504 IScsiAddHeapItem (Heap
, AuthConfig
->ReverseCHAPSecret
, Length
);
505 Target
->ReverseCHAPSecretLength
= Length
;
506 Target
->ReverseCHAPSecretOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
510 *SectionOffset
= (UINT16
) ((UINTN
) Target
- (UINTN
) Table
);
514 // Advance to the next NIC/Target pair
516 Nic
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
*) ((UINTN
) Target
+
517 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE
)));
518 Target
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE
*) ((UINTN
) Nic
+
519 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
)));
531 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
546 EFI_ACPI_SUPPORT_PROTOCOL
*AcpiSupport
;
547 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
;
549 EFI_HANDLE
*HandleBuffer
;
552 EFI_ACPI_TABLE_VERSION Version
;
555 Status
= gBS
->LocateProtocol (&gEfiAcpiSupportProtocolGuid
, NULL
, (void **)&AcpiSupport
);
556 if (EFI_ERROR (Status
)) {
560 // Try to remove the old iSCSI Boot Firmware Table.
562 for (Index
= 0;; Index
++) {
563 Status
= AcpiSupport
->GetAcpiTable (
570 if (EFI_ERROR (Status
)) {
574 Signature
= Table
->Signature
;
577 if (Signature
== EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE
) {
581 Status
= AcpiSupport
->SetAcpiTable (
588 if (EFI_ERROR (Status
)) {
596 // Get all iSCSI private protocols.
598 Status
= gBS
->LocateHandleBuffer (
605 if (EFI_ERROR (Status
)) {
609 // Allocate 4k bytes to hold the ACPI table.
611 Table
= NetAllocatePool (IBFT_MAX_SIZE
);
616 Heap
= (UINT8
*) Table
+ IBFT_HEAP_OFFSET
;
619 // Fill in the various section of the iSCSI Boot Firmware Table.
621 IScsiInitIbfTableHeader (Table
);
622 IScsiInitControlSection (Table
, HandleCount
);
623 IScsiFillInitiatorSection (Table
, &Heap
, HandleBuffer
[0]);
624 IScsiFillNICAndTargetSections (Table
, &Heap
, HandleCount
, HandleBuffer
);
626 NetFreePool (HandleBuffer
);
631 // Install or update the iBFT table.
633 Status
= AcpiSupport
->SetAcpiTable (
637 EFI_ACPI_TABLE_VERSION_3_0
,
640 if (!EFI_ERROR (Status
)) {
641 AcpiSupport
->PublishTables (AcpiSupport
, EFI_ACPI_TABLE_VERSION_3_0
);