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