]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiIbft.c
NetworkPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiIbft.c
1 /** @file
2 Implementation for iSCSI Boot Firmware Table publication.
3
4 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "IScsiImpl.h"
10
11 BOOLEAN mIbftInstalled = FALSE;
12 UINTN mTableKey;
13
14 /**
15 Initialize the header of the iSCSI Boot Firmware Table.
16
17 @param[out] Header The header of the iSCSI Boot Firmware Table.
18 @param[in] OemId The OEM ID.
19 @param[in] OemTableId The OEM table ID for the iBFT.
20
21 **/
22 VOID
23 IScsiInitIbfTableHeader (
24 OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header,
25 IN UINT8 *OemId,
26 IN UINT64 *OemTableId
27 )
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 CopyMem (Header->OemId, OemId, sizeof (Header->OemId));
35 CopyMem (&Header->OemTableId, OemTableId, sizeof (UINT64));
36 }
37
38
39 /**
40 Initialize the control section of the iSCSI Boot Firmware Table.
41
42 @param[in] Table The ACPI table.
43
44 **/
45 VOID
46 IScsiInitControlSection (
47 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table
48 )
49 {
50 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
51 UINTN NumOffset;
52
53 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
54
55 Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;
56 Control->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;
57 Control->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);
58
59 //
60 // If in multipathing mode, enable the Boot Failover Flag.
61 // If in single path mode, disable it. Mix-model is not allowed.
62 //
63 // BUGBUG: if Boot Failover Flag is set to 1, the OS installer cannot
64 // find the iSCSI mapped disk. So still keep not set for single path mode.
65 //
66 if (mPrivate->EnableMpio) {
67 Control->Header.Flags = 0;
68 NumOffset = 2 * (mPrivate->MpioCount - mPrivate->Krb5MpioCount);
69 } else {
70 NumOffset = 2 * mPrivate->ValidSinglePathCount;
71 }
72
73 //
74 // Each attempt occupies two offsets: one for the NIC section;
75 // the other for the Target section.
76 //
77 if (NumOffset > 4) {
78 //
79 // Need expand the control section if more than 2 NIC/Target attempts
80 // exist.
81 //
82 Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));
83 }
84 }
85
86
87 /**
88 Add one item into the heap.
89
90 @param[in, out] Heap On input, the current address of the heap. On output, the address of
91 the heap after the item is added.
92 @param[in] Data The data to add into the heap.
93 @param[in] Len Length of the Data in byte.
94
95 **/
96 VOID
97 IScsiAddHeapItem (
98 IN OUT UINT8 **Heap,
99 IN VOID *Data,
100 IN UINTN Len
101 )
102 {
103 //
104 // Add one byte for the NULL delimiter.
105 //
106 *Heap -= Len + 1;
107
108 CopyMem (*Heap, Data, Len);
109 *(*Heap + Len) = 0;
110 }
111
112
113 /**
114 Fill the Initiator section of the iSCSI Boot Firmware Table.
115
116 @param[in] Table The ACPI table.
117 @param[in, out] Heap The heap.
118
119 **/
120 VOID
121 IScsiFillInitiatorSection (
122 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
123 IN OUT UINT8 **Heap
124 )
125 {
126 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
127 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *Initiator;
128
129 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
130
131 //
132 // Initiator section immediately follows the control section.
133 //
134 Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *)
135 ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));
136
137 Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);
138
139 Initiator->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID;
140 Initiator->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION;
141 Initiator->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);
142 Initiator->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BLOCK_VALID |
143 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED;
144
145 //
146 // Fill the iSCSI Initiator Name into the heap.
147 //
148 IScsiAddHeapItem (Heap, mPrivate->InitiatorName, mPrivate->InitiatorNameLength - 1);
149
150 Initiator->IScsiNameLength = (UINT16) (mPrivate->InitiatorNameLength - 1);
151 Initiator->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
152 }
153
154
155 /**
156 Map the v4 IP address into v6 IP address.
157
158 @param[in] V4 The v4 IP address.
159 @param[out] V6 The v6 IP address.
160
161 **/
162 VOID
163 IScsiMapV4ToV6Addr (
164 IN EFI_IPv4_ADDRESS *V4,
165 OUT EFI_IPv6_ADDRESS *V6
166 )
167 {
168 UINTN Index;
169
170 ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));
171
172 V6->Addr[10] = 0xff;
173 V6->Addr[11] = 0xff;
174
175 for (Index = 0; Index < 4; Index++) {
176 V6->Addr[12 + Index] = V4->Addr[Index];
177 }
178 }
179
180
181 /**
182 Fill the NIC and target sections in iSCSI Boot Firmware Table.
183
184 @param[in] Table The buffer of the ACPI table.
185 @param[in, out] Heap The heap buffer used to store the variable length
186 parameters such as iSCSI name.
187
188 **/
189 VOID
190 IScsiFillNICAndTargetSections (
191 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
192 IN OUT UINT8 **Heap
193 )
194 {
195 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
196 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *Nic;
197 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *Target;
198 ISCSI_SESSION_CONFIG_NVDATA *NvData;
199 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;
200 UINT16 *SectionOffset;
201 UINTN Index;
202 UINT16 Length;
203 LIST_ENTRY *Entry;
204 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt;
205 ISCSI_NIC_INFO *NicInfo;
206 BOOLEAN Flag;
207
208 //
209 // Get the offset of the first Nic and Target section.
210 //
211 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
212 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +
213 Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));
214 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
215 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
216
217 SectionOffset = &Control->NIC0Offset;
218
219 Index = 0;
220 Flag = TRUE;
221
222 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
223 if (Index == 0) {
224 //
225 // First entry should be boot selected entry.
226 //
227 Attempt = IScsiConfigGetAttemptByConfigIndex (mPrivate->BootSelectedIndex);
228 if (Attempt == NULL) {
229 //
230 // First boot selected entry can not be found.
231 //
232 break;
233 }
234
235 ASSERT (Attempt->SessionConfigData.Enabled != ISCSI_DISABLED);
236
237 } else {
238 if (Index == 1 && Flag) {
239 Entry = mPrivate->AttemptConfigs.ForwardLink;
240 Flag = FALSE;
241 }
242
243 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
244 if (Attempt->AttemptConfigIndex == mPrivate->BootSelectedIndex) {
245 continue;
246 }
247 }
248
249 if (Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) {
250 continue;
251 }
252
253 //
254 // Krb5 attempt will not be recorded in iBFT.
255 //
256 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
257 continue;
258 }
259
260 //
261 // If multipath mode is enabled, only the attempts in MPIO will be recorded in iBFT.
262 //
263 if (mPrivate->EnableMpio && Attempt->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO) {
264 continue;
265 }
266
267 //
268 // Only the valid attempts will be recorded.
269 //
270 if (!Attempt->ValidiBFTPath) {
271 continue;
272 }
273
274 NvData = &Attempt->SessionConfigData;
275 AuthConfig = &Attempt->AuthConfigData.CHAP;
276
277 //
278 // Fill the Nic section.
279 //
280
281 Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;
282 Nic->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;
283 Nic->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);
284 Nic->Header.Index = (UINT8) Index;
285 Nic->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |
286 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;
287
288 if (Index == 0) {
289 Nic->Header.Flags |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED;
290 }
291
292 if (NvData->InitiatorInfoFromDhcp) {
293 Nic->Origin = IpPrefixOriginDhcp;
294 } else {
295 Nic->Origin = IpPrefixOriginManual;
296 }
297
298 if (NvData->IpMode == IP_MODE_IP4 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
299 //
300 // Get the subnet mask prefix length.
301 //
302 Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&NvData->SubnetMask);
303
304 //
305 // Map the various v4 addresses into v6 addresses.
306 //
307 IScsiMapV4ToV6Addr (&NvData->LocalIp.v4, &Nic->Ip);
308 IScsiMapV4ToV6Addr (&NvData->Gateway.v4, &Nic->Gateway);
309 IScsiMapV4ToV6Addr (&Attempt->PrimaryDns.v4, &Nic->PrimaryDns);
310 IScsiMapV4ToV6Addr (&Attempt->SecondaryDns.v4, &Nic->SecondaryDns);
311 IScsiMapV4ToV6Addr (&Attempt->DhcpServer.v4, &Nic->DhcpServer);
312
313 } else if (NvData->IpMode == IP_MODE_IP6 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
314
315 Nic->SubnetMaskPrefixLength = NvData->PrefixLength;
316 CopyMem (&Nic->Ip, &NvData->LocalIp, sizeof (EFI_IPv6_ADDRESS));
317 CopyMem (&Nic->Gateway, &NvData->Gateway, sizeof (EFI_IPv6_ADDRESS));
318 CopyMem (&Nic->PrimaryDns, &Attempt->PrimaryDns, sizeof (EFI_IPv6_ADDRESS));
319 CopyMem (&Nic->SecondaryDns, &Attempt->SecondaryDns, sizeof (EFI_IPv6_ADDRESS));
320 CopyMem (&Nic->DhcpServer, &Attempt->DhcpServer, sizeof (EFI_IPv6_ADDRESS));
321
322 } else {
323 ASSERT (FALSE);
324 }
325
326 //
327 // Get Nic Info: VLAN tag, Mac address, PCI location.
328 //
329 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex);
330 ASSERT (NicInfo != NULL);
331
332 Nic->VLanTag = NicInfo->VlanId;
333 CopyMem (Nic->Mac, &NicInfo->PermanentAddress, sizeof (Nic->Mac));
334 Nic->PciLocation = (UINT16) ((NicInfo->BusNumber << 8) |
335 (NicInfo->DeviceNumber << 3) | NicInfo->FunctionNumber);
336 *SectionOffset = (UINT16) ((UINTN) Nic - (UINTN) Table);
337 SectionOffset++;
338
339 //
340 // Fill the Target section.
341 //
342
343 Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;
344 Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;
345 Target->Header.Length = (UINT16) sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);
346 Target->Header.Index = (UINT8) Index;
347 Target->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID;
348
349 if (Index == 0) {
350 Target->Header.Flags |= EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;
351 }
352
353 Target->Port = NvData->TargetPort;
354
355 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
356 if (AuthConfig->CHAPType == ISCSI_CHAP_UNI) {
357 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_CHAP;
358 } else if (AuthConfig->CHAPType == ISCSI_CHAP_MUTUAL) {
359 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP;
360 }
361 } else if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_NONE) {
362 Target->CHAPType = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_NO_CHAP;
363 }
364
365 Target->NicIndex = (UINT8) Index;
366
367 if (NvData->IpMode == IP_MODE_IP4 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
368 IScsiMapV4ToV6Addr (&NvData->TargetIp.v4, &Target->Ip);
369 } else if (NvData->IpMode == IP_MODE_IP6 || NvData->IpMode == IP_MODE_AUTOCONFIG) {
370 CopyMem (&Target->Ip, &NvData->TargetIp, sizeof (EFI_IPv6_ADDRESS));
371 } else {
372 ASSERT (FALSE);
373 }
374
375 CopyMem (Target->BootLun, NvData->BootLun, sizeof (Target->BootLun));
376
377 //
378 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
379 //
380 Length = (UINT16) AsciiStrLen (NvData->TargetName);
381 IScsiAddHeapItem (Heap, NvData->TargetName, Length);
382
383 Target->IScsiNameLength = Length;
384 Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
385
386 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) {
387 //
388 // CHAP Name
389 //
390 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);
391 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);
392 Target->CHAPNameLength = Length;
393 Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
394
395 //
396 // CHAP Secret
397 //
398 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);
399 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);
400 Target->CHAPSecretLength = Length;
401 Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
402
403 if (Target->CHAPType == EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_CHAP_TYPE_MUTUAL_CHAP) {
404 //
405 // Reverse CHAP Name.
406 //
407 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);
408 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);
409 Target->ReverseCHAPNameLength = Length;
410 Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
411
412 //
413 // Reverse CHAP Secret.
414 //
415 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);
416 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);
417 Target->ReverseCHAPSecretLength = Length;
418 Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
419 }
420 }
421
422 *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);
423 SectionOffset++;
424
425 //
426 // Advance to the next NIC/Target pair.
427 //
428 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +
429 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));
430 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
431 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
432
433 Index++;
434 }
435 }
436
437
438 /**
439 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
440 session status.
441
442 **/
443 VOID
444 IScsiPublishIbft (
445 IN VOID
446 )
447 {
448 EFI_STATUS Status;
449 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
450 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;
451 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
452 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
453 EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
454 UINT8 *Heap;
455 UINT8 Checksum;
456
457 Rsdt = NULL;
458 Xsdt = NULL;
459
460 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
461 if (EFI_ERROR (Status)) {
462 return ;
463 }
464
465 //
466 // Find ACPI table RSD_PTR from the system table.
467 //
468 Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) &Rsdp);
469 if (EFI_ERROR (Status)) {
470 Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) &Rsdp);
471 }
472
473 if (EFI_ERROR (Status) || (Rsdp == NULL)) {
474 return ;
475 } else if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION && Rsdp->XsdtAddress != 0) {
476 Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
477 } else if (Rsdp->RsdtAddress != 0) {
478 Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
479 }
480
481 if ((Xsdt == NULL) && (Rsdt == NULL)) {
482 return ;
483 }
484
485 if (mIbftInstalled) {
486 Status = AcpiTableProtocol->UninstallAcpiTable (
487 AcpiTableProtocol,
488 mTableKey
489 );
490 if (EFI_ERROR (Status)) {
491 return ;
492 }
493 mIbftInstalled = FALSE;
494 }
495
496 //
497 // If there is no valid attempt configuration, just return.
498 //
499 if ((!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount == 0) ||
500 (mPrivate->EnableMpio && mPrivate->MpioCount <= mPrivate->Krb5MpioCount)) {
501 return ;
502 }
503
504 //
505 // Allocate 4k bytes to hold the ACPI table.
506 //
507 Table = AllocateZeroPool (IBFT_MAX_SIZE);
508 if (Table == NULL) {
509 return ;
510 }
511
512 Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;
513
514 //
515 // Fill in the various section of the iSCSI Boot Firmware Table.
516 //
517 if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {
518 IScsiInitIbfTableHeader (Table, Xsdt->OemId, &Xsdt->OemTableId);
519 } else {
520 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);
521 }
522
523 IScsiInitControlSection (Table);
524 IScsiFillInitiatorSection (Table, &Heap);
525 IScsiFillNICAndTargetSections (Table, &Heap);
526
527 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);
528 Table->Checksum = Checksum;
529
530 //
531 // Install or update the iBFT table.
532 //
533 Status = AcpiTableProtocol->InstallAcpiTable (
534 AcpiTableProtocol,
535 Table,
536 Table->Length,
537 &mTableKey
538 );
539 if (EFI_ERROR(Status)) {
540 return;
541 }
542
543 mIbftInstalled = TRUE;
544 FreePool (Table);
545 }