TianoCore EDK2 master
Loading...
Searching...
No Matches
IScsiIbft.c
Go to the documentation of this file.
1
9#include "IScsiImpl.h"
10
11BOOLEAN mIbftInstalled = FALSE;
12UINTN mTableKey;
13
22VOID
25 IN UINT8 *OemId,
26 IN UINT64 *OemTableId
27 )
28{
30 Header->Length = IBFT_HEAP_OFFSET;
31 Header->Revision = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;
32 Header->Checksum = 0;
33
34 CopyMem (Header->OemId, OemId, sizeof (Header->OemId));
35 CopyMem (&Header->OemTableId, OemTableId, sizeof (UINT64));
36}
37
44VOID
47 )
48{
50 UINTN NumOffset;
51
53
54 Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;
55 Control->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;
56 Control->Header.Length = (UINT16)sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);
57
58 //
59 // If in multipathing mode, enable the Boot Failover Flag.
60 // If in single path mode, disable it. Mix-model is not allowed.
61 //
62 // BUGBUG: if Boot Failover Flag is set to 1, the OS installer cannot
63 // find the iSCSI mapped disk. So still keep not set for single path mode.
64 //
65 if (mPrivate->EnableMpio) {
66 Control->Header.Flags = 0;
67 NumOffset = 2 * (mPrivate->MpioCount - mPrivate->Krb5MpioCount);
68 } else {
69 NumOffset = 2 * mPrivate->ValidSinglePathCount;
70 }
71
72 //
73 // Each attempt occupies two offsets: one for the NIC section;
74 // the other for the Target section.
75 //
76 if (NumOffset > 4) {
77 //
78 // Need expand the control section if more than 2 NIC/Target attempts
79 // exist.
80 //
81 Control->Header.Length = (UINT16)(Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));
82 }
83}
84
94VOID
96 IN OUT UINT8 **Heap,
97 IN VOID *Data,
98 IN UINTN Len
99 )
100{
101 //
102 // Add one byte for the NULL delimiter.
103 //
104 *Heap -= Len + 1;
105
106 CopyMem (*Heap, Data, Len);
107 *(*Heap + Len) = 0;
108}
109
117VOID
120 IN OUT UINT8 **Heap
121 )
122{
125
127
128 //
129 // Initiator section immediately follows the control section.
130 //
132 ((UINT8 *)Control + IBFT_ROUNDUP (Control->Header.Length));
133
134 Control->InitiatorOffset = (UINT16)((UINTN)Initiator - (UINTN)Table);
135
136 Initiator->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID;
137 Initiator->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION;
138 Initiator->Header.Length = (UINT16)sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);
139 Initiator->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BLOCK_VALID |
140 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED;
141
142 //
143 // Fill the iSCSI Initiator Name into the heap.
144 //
145 IScsiAddHeapItem (Heap, mPrivate->InitiatorName, mPrivate->InitiatorNameLength - 1);
146
147 Initiator->IScsiNameLength = (UINT16)(mPrivate->InitiatorNameLength - 1);
148 Initiator->IScsiNameOffset = (UINT16)((UINTN)*Heap - (UINTN)Table);
149}
150
158VOID
162 )
163{
164 UINTN Index;
165
166 ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));
167
168 V6->Addr[10] = 0xff;
169 V6->Addr[11] = 0xff;
170
171 for (Index = 0; Index < 4; Index++) {
172 V6->Addr[12 + Index] = V4->Addr[Index];
173 }
174}
175
184VOID
187 IN OUT UINT8 **Heap
188 )
189{
195 UINT16 *SectionOffset;
196 UINTN Index;
197 UINT16 Length;
198 LIST_ENTRY *Entry;
200 ISCSI_NIC_INFO *NicInfo;
201 BOOLEAN Flag;
202
203 //
204 // Get the offset of the first Nic and Target section.
205 //
208 Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));
211
212 SectionOffset = &Control->NIC0Offset;
213
214 Index = 0;
215 Flag = TRUE;
216
217 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
218 if (Index == 0) {
219 //
220 // First entry should be boot selected entry.
221 //
222 Attempt = IScsiConfigGetAttemptByConfigIndex (mPrivate->BootSelectedIndex);
223 if (Attempt == NULL) {
224 //
225 // First boot selected entry can not be found.
226 //
227 break;
228 }
229
230 ASSERT (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED);
231 } else {
232 if ((Index == 1) && Flag) {
233 Entry = mPrivate->AttemptConfigs.ForwardLink;
234 Flag = FALSE;
235 }
236
237 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
238 if (Attempt->AttemptConfigIndex == mPrivate->BootSelectedIndex) {
239 continue;
240 }
241 }
242
243 if (Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
244 continue;
245 }
246
247 //
248 // Krb5 attempt will not be recorded in iBFT.
249 //
250 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
251 continue;
252 }
253
254 //
255 // If multipath mode is enabled, only the attempts in MPIO will be recorded in iBFT.
256 //
257 if (mPrivate->EnableMpio && (Attempt->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO)) {
258 continue;
259 }
260
261 //
262 // Only the valid attempts will be recorded.
263 //
264 if (!Attempt->ValidiBFTPath) {
265 continue;
266 }
267
268 NvData = &Attempt->SessionConfigData;
269 AuthConfig = &Attempt->AuthConfigData.CHAP;
270
271 //
272 // Fill the Nic section.
273 //
274
275 Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;
276 Nic->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;
277 Nic->Header.Length = (UINT16)sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);
278 Nic->Header.Index = (UINT8)Index;
279 Nic->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |
280 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;
281
282 if (Index == 0) {
283 Nic->Header.Flags |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED;
284 }
285
286 if (NvData->InitiatorInfoFromDhcp) {
287 Nic->Origin = IpPrefixOriginDhcp;
288 } else {
289 Nic->Origin = IpPrefixOriginManual;
290 }
291
292 if ((NvData->IpMode == IP_MODE_IP4) || (NvData->IpMode == IP_MODE_AUTOCONFIG)) {
293 //
294 // Get the subnet mask prefix length.
295 //
296 Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&NvData->SubnetMask);
297
298 //
299 // Map the various v4 addresses into v6 addresses.
300 //
301 IScsiMapV4ToV6Addr (&NvData->LocalIp.v4, &Nic->Ip);
302 IScsiMapV4ToV6Addr (&NvData->Gateway.v4, &Nic->Gateway);
303 IScsiMapV4ToV6Addr (&Attempt->PrimaryDns.v4, &Nic->PrimaryDns);
304 IScsiMapV4ToV6Addr (&Attempt->SecondaryDns.v4, &Nic->SecondaryDns);
305 IScsiMapV4ToV6Addr (&Attempt->DhcpServer.v4, &Nic->DhcpServer);
306 } else if ((NvData->IpMode == IP_MODE_IP6) || (NvData->IpMode == IP_MODE_AUTOCONFIG)) {
307 Nic->SubnetMaskPrefixLength = NvData->PrefixLength;
308 CopyMem (&Nic->Ip, &NvData->LocalIp, sizeof (EFI_IPv6_ADDRESS));
309 CopyMem (&Nic->Gateway, &NvData->Gateway, sizeof (EFI_IPv6_ADDRESS));
310 CopyMem (&Nic->PrimaryDns, &Attempt->PrimaryDns, sizeof (EFI_IPv6_ADDRESS));
311 CopyMem (&Nic->SecondaryDns, &Attempt->SecondaryDns, sizeof (EFI_IPv6_ADDRESS));
312 CopyMem (&Nic->DhcpServer, &Attempt->DhcpServer, sizeof (EFI_IPv6_ADDRESS));
313 } else {
314 ASSERT (FALSE);
315 }
316
317 //
318 // Get Nic Info: VLAN tag, Mac address, PCI location.
319 //
320 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);
321 ASSERT (NicInfo != NULL);
322
323 Nic->VLanTag = NicInfo->VlanId;
324 CopyMem (Nic->Mac, &NicInfo->PermanentAddress, sizeof (Nic->Mac));
325 Nic->PciLocation = (UINT16)((NicInfo->BusNumber << 8) |
326 (NicInfo->DeviceNumber << 3) | NicInfo->FunctionNumber);
327 *SectionOffset = (UINT16)((UINTN)Nic - (UINTN)Table);
328 SectionOffset++;
329
330 //
331 // Fill the Target section.
332 //
333
334 Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;
335 Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;
336 Target->Header.Length = (UINT16)sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);
337 Target->Header.Index = (UINT8)Index;
338 Target->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID;
339
340 if (Index == 0) {
341 Target->Header.Flags |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;
342 }
343
344 Target->Port = NvData->TargetPort;
345
346 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
347 if (AuthConfig->CHAPType == ISCSI_CHAP_UNI) {
348 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_CHAP;
349 } else if (AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
350 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP;
351 }
352 } else if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_NONE) {
353 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP;
354 }
355
356 Target->NicIndex = (UINT8)Index;
357
358 if ((NvData->IpMode == IP_MODE_IP4) || (NvData->IpMode == IP_MODE_AUTOCONFIG)) {
359 IScsiMapV4ToV6Addr (&NvData->TargetIp.v4, &Target->Ip);
360 } else if ((NvData->IpMode == IP_MODE_IP6) || (NvData->IpMode == IP_MODE_AUTOCONFIG)) {
361 CopyMem (&Target->Ip, &NvData->TargetIp, sizeof (EFI_IPv6_ADDRESS));
362 } else {
363 ASSERT (FALSE);
364 }
365
366 CopyMem (Target->BootLun, NvData->BootLun, sizeof (Target->BootLun));
367
368 //
369 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
370 //
371 Length = (UINT16)AsciiStrLen (NvData->TargetName);
372 IScsiAddHeapItem (Heap, NvData->TargetName, Length);
373
374 Target->IScsiNameLength = Length;
375 Target->IScsiNameOffset = (UINT16)((UINTN)*Heap - (UINTN)Table);
376
377 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
378 //
379 // CHAP Name
380 //
381 Length = (UINT16)AsciiStrLen (AuthConfig->CHAPName);
382 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);
383 Target->CHAPNameLength = Length;
384 Target->CHAPNameOffset = (UINT16)((UINTN)*Heap - (UINTN)Table);
385
386 //
387 // CHAP Secret
388 //
389 Length = (UINT16)AsciiStrLen (AuthConfig->CHAPSecret);
390 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);
391 Target->CHAPSecretLength = Length;
392 Target->CHAPSecretOffset = (UINT16)((UINTN)*Heap - (UINTN)Table);
393
394 if (Target->CHAPType == EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP) {
395 //
396 // Reverse CHAP Name.
397 //
398 Length = (UINT16)AsciiStrLen (AuthConfig->ReverseCHAPName);
399 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);
400 Target->ReverseCHAPNameLength = Length;
401 Target->ReverseCHAPNameOffset = (UINT16)((UINTN)*Heap - (UINTN)Table);
402
403 //
404 // Reverse CHAP Secret.
405 //
406 Length = (UINT16)AsciiStrLen (AuthConfig->ReverseCHAPSecret);
407 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);
408 Target->ReverseCHAPSecretLength = Length;
409 Target->ReverseCHAPSecretOffset = (UINT16)((UINTN)*Heap - (UINTN)Table);
410 }
411 }
412
413 *SectionOffset = (UINT16)((UINTN)Target - (UINTN)Table);
414 SectionOffset++;
415
416 //
417 // Advance to the next NIC/Target pair.
418 //
423
424 Index++;
425 }
426}
427
433VOID
435 IN VOID
436 )
437{
438 EFI_STATUS Status;
439 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
444 UINT8 *Heap;
445 UINT8 Checksum;
446
447 Rsdt = NULL;
448 Xsdt = NULL;
449
450 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
451 if (EFI_ERROR (Status)) {
452 return;
453 }
454
455 //
456 // Find ACPI table RSD_PTR from the system table.
457 //
458 Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)&Rsdp);
459 if (EFI_ERROR (Status)) {
460 Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&Rsdp);
461 }
462
463 if (EFI_ERROR (Status) || (Rsdp == NULL)) {
464 return;
465 } else if ((Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) && (Rsdp->XsdtAddress != 0)) {
466 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress;
467 } else if (Rsdp->RsdtAddress != 0) {
468 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress;
469 }
470
471 if ((Xsdt == NULL) && (Rsdt == NULL)) {
472 return;
473 }
474
475 if (mIbftInstalled) {
476 Status = AcpiTableProtocol->UninstallAcpiTable (
477 AcpiTableProtocol,
478 mTableKey
479 );
480 if (EFI_ERROR (Status)) {
481 return;
482 }
483
484 mIbftInstalled = FALSE;
485 }
486
487 //
488 // If there is no valid attempt configuration, just return.
489 //
490 if ((!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount == 0)) ||
491 (mPrivate->EnableMpio && (mPrivate->MpioCount <= mPrivate->Krb5MpioCount)))
492 {
493 return;
494 }
495
496 //
497 // Allocate 4k bytes to hold the ACPI table.
498 //
499 Table = AllocateZeroPool (IBFT_MAX_SIZE);
500 if (Table == NULL) {
501 return;
502 }
503
504 Heap = (UINT8 *)Table + IBFT_HEAP_OFFSET;
505
506 //
507 // Fill in the various section of the iSCSI Boot Firmware Table.
508 //
510 IScsiInitIbfTableHeader (Table, Xsdt->OemId, &Xsdt->OemTableId);
511 } else {
512 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);
513 }
514
516 IScsiFillInitiatorSection (Table, &Heap);
517 IScsiFillNICAndTargetSections (Table, &Heap);
518
519 Checksum = CalculateCheckSum8 ((UINT8 *)Table, Table->Length);
520 Table->Checksum = Checksum;
521
522 //
523 // Install or update the iBFT table.
524 //
525 Status = AcpiTableProtocol->InstallAcpiTable (
526 AcpiTableProtocol,
527 Table,
528 Table->Length,
529 &mTableKey
530 );
531 if (EFI_ERROR (Status)) {
532 return;
533 }
534
535 mIbftInstalled = TRUE;
536 FreePool (Table);
537}
UINT64 UINTN
#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION
Definition: Acpi20.h:87
#define EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE
Definition: Acpi30.h:733
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
UINT8 EFIAPI CalculateCheckSum8(IN CONST UINT8 *Buffer, IN UINTN Length)
Definition: CheckSum.c:71
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
ISCSI_ATTEMPT_CONFIG_NVDATA * IScsiConfigGetAttemptByConfigIndex(IN UINT8 AttemptConfigIndex)
Definition: IScsiConfig.c:391
VOID IScsiFillNICAndTargetSections(IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table, IN OUT UINT8 **Heap)
Definition: IScsiIbft.c:185
VOID IScsiFillInitiatorSection(IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table, IN OUT UINT8 **Heap)
Definition: IScsiIbft.c:118
VOID IScsiInitIbfTableHeader(OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header, IN UINT8 *OemId, IN UINT64 *OemTableId)
Definition: IScsiIbft.c:23
VOID IScsiInitControlSection(IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table)
Definition: IScsiIbft.c:45
VOID IScsiPublishIbft(IN VOID)
Definition: IScsiIbft.c:434
VOID IScsiAddHeapItem(IN OUT UINT8 **Heap, IN VOID *Data, IN UINTN Len)
Definition: IScsiIbft.c:95
VOID IScsiMapV4ToV6Addr(IN EFI_IPv4_ADDRESS *V4, OUT EFI_IPv6_ADDRESS *V6)
Definition: IScsiIbft.c:159
UINT8 IScsiGetSubnetMaskPrefixLength(IN EFI_IPv4_ADDRESS *SubnetMask)
Definition: IScsiMisc.c:76
ISCSI_NIC_INFO * IScsiGetNicInfoByIndex(IN UINT8 NicIndex)
Definition: IScsiMisc.c:1610
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82