3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
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
);