2 Implementation for iSCSI Boot Firmware Table publication.
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
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.
15 #include "IScsiImpl.h"
18 Initialize the header of the iSCSI Boot Firmware Table.
20 @param[in] Header The header of the iSCSI Boot Firmware Table.
23 IScsiInitIbfTableHeader (
24 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Header
27 ZeroMem (Header
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
));
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
;
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';
42 Initialize the control section of the iSCSI Boot Firmware Table.
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.
49 IScsiInitControlSection (
50 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
,
54 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*Control
;
57 Control
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*) (Table
+ 1);
59 ZeroMem (Control
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
));
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
);
66 // Each session occupies two offsets, one for the NIC section,
67 // the other for the Target section.
69 NumOffset
= 2 * HandleCount
;
72 // Need expand the control section if more than 2 NIC/Target sections
75 Control
->Header
.Length
= (UINT16
) (Control
->Header
.Length
+ (NumOffset
- 4) * sizeof (UINT16
));
80 Add one item into the heap.
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.
95 // Add one byte for the NULL delimiter.
99 CopyMem (*Heap
, Data
, Len
);
104 Fill the Initiator section of the iSCSI Boot Firmware Table.
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.
111 IScsiFillInitiatorSection (
112 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
,
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
;
124 Control
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE
*) (Table
+ 1);
127 // Initiator section immediately follows the control section.
129 Initiator
= (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE
*) ((UINT8
*) Control
+ IBFT_ROUNDUP (Control
->Header
.Length
));
131 Control
->InitiatorOffset
= (UINT16
) ((UINTN
) Initiator
- (UINTN
) Table
);
133 ZeroMem (Initiator
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE
));
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
;
141 // Get the identifier from the handle.
143 Status
= gBS
->HandleProtocol (Handle
, &mIScsiPrivateGuid
, (VOID
**) &IScsiIdentifier
);
144 if (EFI_ERROR (Status
)) {
149 DriverData
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
150 Session
= &DriverData
->Session
;
153 // Fill the iSCSI Initiator Name into the heap.
155 IScsiAddHeapItem (Heap
, Session
->InitiatorName
, Session
->InitiatorNameLength
- 1);
157 Initiator
->IScsiNameLength
= (UINT16
) (Session
->InitiatorNameLength
- 1);
158 Initiator
->IScsiNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
162 Map the v4 IP address into v6 IP address.
164 @param[in] V4 The v4 IP address.
165 @param[out] V6 The v6 IP address.
169 IN EFI_IPv4_ADDRESS
*V4
,
170 OUT EFI_IPv6_ADDRESS
*V6
175 ZeroMem (V6
, sizeof (EFI_IPv6_ADDRESS
));
180 for (Index
= 0; Index
< 4; Index
++) {
181 V6
->Addr
[12 + Index
] = V4
->Addr
[Index
];
186 Get the NIC's PCI location and return it accroding to the composited
187 format defined in iSCSI Boot Firmware Table.
189 @param[in] Controller The handle of the controller.
191 @return UINT16 The composited representation of the NIC PCI location.
192 @retval 0 Other errors as indicated.
195 IScsiGetNICPciLocation (
196 IN EFI_HANDLE Controller
200 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
201 EFI_HANDLE PciIoHandle
;
202 EFI_PCI_IO_PROTOCOL
*PciIo
;
208 Status
= gBS
->HandleProtocol (
210 &gEfiDevicePathProtocolGuid
,
213 if (EFI_ERROR (Status
)) {
217 Status
= gBS
->LocateDevicePath (
218 &gEfiPciIoProtocolGuid
,
222 if (EFI_ERROR (Status
)) {
226 Status
= gBS
->HandleProtocol (PciIoHandle
, &gEfiPciIoProtocolGuid
, (VOID
**)&PciIo
);
227 if (EFI_ERROR (Status
)) {
231 Status
= PciIo
->GetLocation (PciIo
, &Segment
, &Bus
, &Device
, &Function
);
232 if (EFI_ERROR (Status
)) {
236 return (UINT16
) ((Bus
<< 8) | (Device
<< 3) | Function
);
240 Get the MAC address of the controller.
242 @param[in] Controller The handle of the controller.
244 @return EFI_MAC_ADDRESS * The mac address.
248 IN EFI_HANDLE Controller
252 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
254 Status
= gBS
->HandleProtocol (
256 &gEfiSimpleNetworkProtocolGuid
,
259 ASSERT_EFI_ERROR (Status
);
261 return &Snp
->Mode
->PermanentAddress
;
265 Fill the NIC and target sections in iSCSI Boot Firmware Table.
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.
273 IScsiFillNICAndTargetSections (
274 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
,
276 IN UINTN HandleCount
,
277 IN EFI_HANDLE
*Handles
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
;
289 EFI_MAC_ADDRESS
*Mac
;
290 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
294 // Get the offset of the first Nic and Target section.
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
)));
302 SectionOffset
= &Control
->NIC0Offset
;
304 for (Index
= 0; Index
< HandleCount
; Index
++) {
305 Status
= gBS
->HandleProtocol (Handles
[Index
], &mIScsiPrivateGuid
, (VOID
**)&IScsiIdentifier
);
306 if (EFI_ERROR (Status
)) {
311 DriverData
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
312 SessionConfigData
= &DriverData
->Session
.ConfigData
;
313 AuthConfig
= &DriverData
->Session
.AuthData
.AuthConfig
;
316 // Fill the Nic section.
318 ZeroMem (Nic
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE
));
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
;
329 // Get the subnet mask prefix length.
331 Nic
->SubnetMaskPrefixLength
= IScsiGetSubnetMaskPrefixLength (&SessionConfigData
->NvData
.SubnetMask
);
333 if (SessionConfigData
->NvData
.InitiatorInfoFromDhcp
) {
334 Nic
->Origin
= IpPrefixOriginDhcp
;
336 Nic
->Origin
= IpPrefixOriginManual
;
339 // Map the various v4 addresses into v6 addresses.
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
);
347 Mac
= IScsiGetMacAddress (DriverData
->Controller
);
348 CopyMem (Nic
->Mac
, Mac
, sizeof (Nic
->Mac
));
351 // Get the PCI location of the Nic.
353 Nic
->PciLocation
= IScsiGetNICPciLocation (DriverData
->Controller
);
355 *SectionOffset
= (UINT16
) ((UINTN
) Nic
- (UINTN
) Table
);
359 // Fill the Target section.
361 ZeroMem (Target
, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE
));
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
;
372 IScsiMapV4ToV6Addr (&SessionConfigData
->NvData
.TargetIp
, &Target
->Ip
);
373 CopyMem (Target
->BootLun
, SessionConfigData
->NvData
.BootLun
, sizeof (Target
->BootLun
));
376 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
378 Length
= (UINT16
) AsciiStrLen (SessionConfigData
->NvData
.TargetName
);
379 IScsiAddHeapItem (Heap
, SessionConfigData
->NvData
.TargetName
, Length
);
381 Target
->IScsiNameLength
= Length
;
382 Target
->IScsiNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
384 if (Target
->CHAPType
!= ISCSI_CHAP_NONE
) {
388 Length
= (UINT16
) AsciiStrLen (AuthConfig
->CHAPName
);
389 IScsiAddHeapItem (Heap
, AuthConfig
->CHAPName
, Length
);
390 Target
->CHAPNameLength
= Length
;
391 Target
->CHAPNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
396 Length
= (UINT16
) AsciiStrLen (AuthConfig
->CHAPSecret
);
397 IScsiAddHeapItem (Heap
, AuthConfig
->CHAPSecret
, Length
);
398 Target
->CHAPSecretLength
= Length
;
399 Target
->CHAPSecretOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
401 if (Target
->CHAPType
== ISCSI_CHAP_MUTUAL
) {
405 Length
= (UINT16
) AsciiStrLen (AuthConfig
->ReverseCHAPName
);
406 IScsiAddHeapItem (Heap
, AuthConfig
->ReverseCHAPName
, Length
);
407 Target
->ReverseCHAPNameLength
= Length
;
408 Target
->ReverseCHAPNameOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
411 // Reverse CHAP Secret
413 Length
= (UINT16
) AsciiStrLen (AuthConfig
->ReverseCHAPSecret
);
414 IScsiAddHeapItem (Heap
, AuthConfig
->ReverseCHAPSecret
, Length
);
415 Target
->ReverseCHAPSecretLength
= Length
;
416 Target
->ReverseCHAPSecretOffset
= (UINT16
) ((UINTN
) *Heap
- (UINTN
) Table
);
420 *SectionOffset
= (UINT16
) ((UINTN
) Target
- (UINTN
) Table
);
424 // Advance to the next NIC/Target pair
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
)));
434 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
444 EFI_ACPI_SUPPORT_PROTOCOL
*AcpiSupport
;
445 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER
*Table
;
447 EFI_HANDLE
*HandleBuffer
;
450 EFI_ACPI_TABLE_VERSION Version
;
453 Status
= gBS
->LocateProtocol (&gEfiAcpiSupportProtocolGuid
, NULL
, (VOID
**)&AcpiSupport
);
454 if (EFI_ERROR (Status
)) {
458 // Try to remove the old iSCSI Boot Firmware Table.
460 for (Index
= 0;; Index
++) {
461 Status
= AcpiSupport
->GetAcpiTable (
468 if (EFI_ERROR (Status
)) {
472 Signature
= Table
->Signature
;
473 gBS
->FreePool (Table
);
475 if (Signature
== EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE
) {
479 Status
= AcpiSupport
->SetAcpiTable (
486 if (EFI_ERROR (Status
)) {
494 // Get all iSCSI private protocols.
496 Status
= gBS
->LocateHandleBuffer (
503 if (EFI_ERROR (Status
)) {
507 // Allocate 4k bytes to hold the ACPI table.
509 Table
= AllocatePool (IBFT_MAX_SIZE
);
514 Heap
= (UINT8
*) Table
+ IBFT_HEAP_OFFSET
;
517 // Fill in the various section of the iSCSI Boot Firmware Table.
519 IScsiInitIbfTableHeader (Table
);
520 IScsiInitControlSection (Table
, HandleCount
);
521 IScsiFillInitiatorSection (Table
, &Heap
, HandleBuffer
[0]);
522 IScsiFillNICAndTargetSections (Table
, &Heap
, HandleCount
, HandleBuffer
);
524 gBS
->FreePool (HandleBuffer
);
529 // Install or update the iBFT table.
531 Status
= AcpiSupport
->SetAcpiTable (
535 EFI_ACPI_TABLE_VERSION_3_0
,
538 if (!EFI_ERROR (Status
)) {
539 AcpiSupport
->PublishTables (AcpiSupport
, EFI_ACPI_TABLE_VERSION_3_0
);
542 gBS
->FreePool (Table
);