]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiIbft.c
Code clean up in NetLib:
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiIbft.c
1 /** @file
2 Implementation for iSCSI Boot Firmware Table publication.
3
4 Copyright (c) 2004 - 2009, 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
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 VOID
28 IScsiInitIbfTableHeader (
29 OUT EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header,
30 IN UINT8 *OemId,
31 IN UINT64 *OemTableId
32 )
33 {
34 ZeroMem (Header, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER));
35
36 Header->Signature = EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE;
37 Header->Length = IBFT_HEAP_OFFSET;
38 Header->Revision = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;
39 Header->Checksum = 0;
40
41 Header->OemId[0] = 'I';
42 Header->OemId[1] = 'N';
43 Header->OemId[2] = 'T';
44 Header->OemId[3] = 'E';
45 Header->OemId[4] = 'L';
46
47 CopyMem (Header->OemId, OemId, sizeof (Header->OemId));
48 Header->OemTableId = *OemTableId;
49 }
50
51 /**
52 Initialize the control section of the iSCSI Boot Firmware Table.
53
54 @param[in] Table The ACPI table.
55 @param[in] HandleCount The number of the handles associated with iSCSI sessions, it's
56 equal to the number of iSCSI sessions.
57 **/
58 VOID
59 IScsiInitControlSection (
60 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
61 IN UINTN HandleCount
62 )
63 {
64 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
65 UINTN NumOffset;
66
67 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
68
69 ZeroMem (Control, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE));
70
71 Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;
72 Control->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;
73 Control->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);
74
75 //
76 // Each session occupies two offsets, one for the NIC section,
77 // the other for the Target section.
78 //
79 NumOffset = 2 * HandleCount;
80 if (NumOffset > 4) {
81 //
82 // Need expand the control section if more than 2 NIC/Target sections
83 // exist.
84 //
85 Control->Header.Length = (UINT16) (Control->Header.Length + (NumOffset - 4) * sizeof (UINT16));
86 }
87 }
88
89 /**
90 Add one item into the heap.
91
92 @param[in, out] Heap On input, the current address of the heap; On output, the address of
93 the heap after the item is added.
94 @param[in] Data The data to add into the heap.
95 @param[in] Len Length of the Data in byte.
96 **/
97 VOID
98 IScsiAddHeapItem (
99 IN OUT UINT8 **Heap,
100 IN VOID *Data,
101 IN UINTN Len
102 )
103 {
104 //
105 // Add one byte for the NULL delimiter.
106 //
107 *Heap -= Len + 1;
108
109 CopyMem (*Heap, Data, Len);
110 *(*Heap + Len) = 0;
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 @param[in] Handle The handle associated with the iSCSI session.
119 **/
120 VOID
121 IScsiFillInitiatorSection (
122 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
123 IN OUT UINT8 **Heap,
124 IN EFI_HANDLE Handle
125 )
126 {
127 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
128 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *Initiator;
129 ISCSI_DRIVER_DATA *DriverData;
130 ISCSI_SESSION *Session;
131 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
132 EFI_STATUS Status;
133
134 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
135
136 //
137 // Initiator section immediately follows the control section.
138 //
139 Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *) ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));
140
141 Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);
142
143 ZeroMem (Initiator, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE));
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 = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);
148 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;
149
150 //
151 // Get the identifier from the handle.
152 //
153 Status = gBS->HandleProtocol (Handle, &gIScsiPrivateGuid, (VOID **) &IScsiIdentifier);
154 if (EFI_ERROR (Status)) {
155 ASSERT (FALSE);
156 return ;
157 }
158
159 DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
160 Session = &DriverData->Session;
161
162 //
163 // Fill the iSCSI Initiator Name into the heap.
164 //
165 IScsiAddHeapItem (Heap, Session->InitiatorName, Session->InitiatorNameLength - 1);
166
167 Initiator->IScsiNameLength = (UINT16) (Session->InitiatorNameLength - 1);
168 Initiator->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
169 }
170
171 /**
172 Map the v4 IP address into v6 IP address.
173
174 @param[in] V4 The v4 IP address.
175 @param[out] V6 The v6 IP address.
176 **/
177 VOID
178 IScsiMapV4ToV6Addr (
179 IN EFI_IPv4_ADDRESS *V4,
180 OUT EFI_IPv6_ADDRESS *V6
181 )
182 {
183 UINTN Index;
184
185 ZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));
186
187 V6->Addr[10] = 0xff;
188 V6->Addr[11] = 0xff;
189
190 for (Index = 0; Index < 4; Index++) {
191 V6->Addr[12 + Index] = V4->Addr[Index];
192 }
193 }
194
195 /**
196 Get the NIC's PCI location and return it accroding to the composited
197 format defined in iSCSI Boot Firmware Table.
198
199 @param[in] Controller The handle of the controller.
200
201 @return UINT16 The composited representation of the NIC PCI location.
202 @retval 0 Other errors as indicated.
203 **/
204 UINT16
205 IScsiGetNICPciLocation (
206 IN EFI_HANDLE Controller
207 )
208 {
209 EFI_STATUS Status;
210 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
211 EFI_HANDLE PciIoHandle;
212 EFI_PCI_IO_PROTOCOL *PciIo;
213 UINTN Segment;
214 UINTN Bus;
215 UINTN Device;
216 UINTN Function;
217
218 Status = gBS->HandleProtocol (
219 Controller,
220 &gEfiDevicePathProtocolGuid,
221 (VOID **)&DevicePath
222 );
223 if (EFI_ERROR (Status)) {
224 return 0;
225 }
226
227 Status = gBS->LocateDevicePath (
228 &gEfiPciIoProtocolGuid,
229 &DevicePath,
230 &PciIoHandle
231 );
232 if (EFI_ERROR (Status)) {
233 return 0;
234 }
235
236 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);
237 if (EFI_ERROR (Status)) {
238 return 0;
239 }
240
241 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
242 if (EFI_ERROR (Status)) {
243 return 0;
244 }
245
246 return (UINT16) ((Bus << 8) | (Device << 3) | Function);
247 }
248
249 /**
250 Get the MAC address of the controller.
251
252 @param[in] Controller The handle of the controller.
253
254 @return EFI_MAC_ADDRESS * The mac address.
255 **/
256 EFI_MAC_ADDRESS *
257 IScsiGetMacAddress (
258 IN EFI_HANDLE Controller
259 )
260 {
261 EFI_STATUS Status;
262 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
263
264 Status = gBS->HandleProtocol (
265 Controller,
266 &gEfiSimpleNetworkProtocolGuid,
267 (VOID **) &Snp
268 );
269 ASSERT_EFI_ERROR (Status);
270
271 return &Snp->Mode->PermanentAddress;
272 }
273
274 /**
275 Fill the NIC and target sections in iSCSI Boot Firmware Table.
276
277 @param[in] Table The buffer of the ACPI table.
278 @param[in, out] Heap The heap buffer used to store the variable length parameters such as iSCSI name.
279 @param[in] HandleCount Count The number of handles having iSCSI private protocol installed.
280 @param[in] Handles The handle buffer.
281 **/
282 VOID
283 IScsiFillNICAndTargetSections (
284 IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
285 IN OUT UINT8 **Heap,
286 IN UINTN HandleCount,
287 IN EFI_HANDLE *Handles
288 )
289 {
290 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
291 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *Nic;
292 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *Target;
293 ISCSI_DRIVER_DATA *DriverData;
294 ISCSI_SESSION_CONFIG_DATA *SessionConfigData;
295 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;
296 UINT16 *SectionOffset;
297 UINTN Index;
298 UINT16 Length;
299 EFI_MAC_ADDRESS *Mac;
300 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
301 EFI_STATUS Status;
302
303 //
304 // Get the offset of the first Nic and Target section.
305 //
306 Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
307 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +
308 Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));
309 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
310 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
311
312 SectionOffset = &Control->NIC0Offset;
313
314 for (Index = 0; Index < HandleCount; Index++) {
315 Status = gBS->HandleProtocol (Handles[Index], &gIScsiPrivateGuid, (VOID **)&IScsiIdentifier);
316 if (EFI_ERROR (Status)) {
317 ASSERT (FALSE);
318 return ;
319 }
320
321 DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
322 SessionConfigData = &DriverData->Session.ConfigData;
323 AuthConfig = &DriverData->Session.AuthData.AuthConfig;
324
325 //
326 // Fill the Nic section.
327 //
328 ZeroMem (Nic, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE));
329
330 Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;
331 Nic->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;
332 Nic->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);
333 Nic->Header.Index = (UINT8) Index;
334 Nic->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |
335 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED |
336 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;
337
338 //
339 // Get the subnet mask prefix length.
340 //
341 Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&SessionConfigData->NvData.SubnetMask);
342
343 if (SessionConfigData->NvData.InitiatorInfoFromDhcp) {
344 Nic->Origin = IpPrefixOriginDhcp;
345 } else {
346 Nic->Origin = IpPrefixOriginManual;
347 }
348 //
349 // Map the various v4 addresses into v6 addresses.
350 //
351 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.LocalIp, &Nic->Ip);
352 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.Gateway, &Nic->Gateway);
353 IScsiMapV4ToV6Addr (&SessionConfigData->PrimaryDns, &Nic->PrimaryDns);
354 IScsiMapV4ToV6Addr (&SessionConfigData->SecondaryDns, &Nic->SecondaryDns);
355 IScsiMapV4ToV6Addr (&SessionConfigData->DhcpServer, &Nic->DhcpServer);
356
357 Mac = IScsiGetMacAddress (DriverData->Controller);
358 CopyMem (Nic->Mac, Mac, sizeof (Nic->Mac));
359
360 //
361 // Get the PCI location of the Nic.
362 //
363 Nic->PciLocation = IScsiGetNICPciLocation (DriverData->Controller);
364
365 *SectionOffset = (UINT16) ((UINTN) Nic - (UINTN) Table);
366 SectionOffset++;
367
368 //
369 // Fill the Target section.
370 //
371 ZeroMem (Target, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE));
372
373 Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;
374 Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;
375 Target->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);
376 Target->Header.Index = (UINT8) Index;
377 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;
378 Target->Port = SessionConfigData->NvData.TargetPort;
379 Target->CHAPType = AuthConfig->CHAPType;
380 Target->NicIndex = (UINT8) Index;
381
382 IScsiMapV4ToV6Addr (&SessionConfigData->NvData.TargetIp, &Target->Ip);
383 CopyMem (Target->BootLun, SessionConfigData->NvData.BootLun, sizeof (Target->BootLun));
384
385 //
386 // Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
387 //
388 Length = (UINT16) AsciiStrLen (SessionConfigData->NvData.TargetName);
389 IScsiAddHeapItem (Heap, SessionConfigData->NvData.TargetName, Length);
390
391 Target->IScsiNameLength = Length;
392 Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
393
394 if (Target->CHAPType != ISCSI_CHAP_NONE) {
395 //
396 // CHAP Name
397 //
398 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);
399 IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);
400 Target->CHAPNameLength = Length;
401 Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
402
403 //
404 // CHAP Secret
405 //
406 Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);
407 IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);
408 Target->CHAPSecretLength = Length;
409 Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
410
411 if (Target->CHAPType == ISCSI_CHAP_MUTUAL) {
412 //
413 // Reverse CHAP Name
414 //
415 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);
416 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);
417 Target->ReverseCHAPNameLength = Length;
418 Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
419
420 //
421 // Reverse CHAP Secret
422 //
423 Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);
424 IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);
425 Target->ReverseCHAPSecretLength = Length;
426 Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
427 }
428 }
429
430 *SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);
431 SectionOffset++;
432
433 //
434 // Advance to the next NIC/Target pair
435 //
436 Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +
437 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));
438 Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
439 IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
440 }
441 }
442
443 /**
444 Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
445 session status.
446 **/
447 VOID
448 IScsiPublishIbft (
449 VOID
450 )
451 {
452 EFI_STATUS Status;
453 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
454 EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;
455 UINTN HandleCount;
456 EFI_HANDLE *HandleBuffer;
457 UINT8 *Heap;
458 UINT8 Checksum;
459 UINTN Index;
460 EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
461 EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
462
463 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
464 if (EFI_ERROR (Status)) {
465 return ;
466 }
467
468
469 //
470 // Find ACPI table RSD_PTR from 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
492 if (mIbftInstalled) {
493 Status = AcpiTableProtocol->UninstallAcpiTable (
494 AcpiTableProtocol,
495 mTableKey
496 );
497 if (EFI_ERROR (Status)) {
498 return ;
499 }
500 mIbftInstalled = FALSE;
501 }
502
503 //
504 // Get all iSCSI private protocols.
505 //
506 Status = gBS->LocateHandleBuffer (
507 ByProtocol,
508 &gIScsiPrivateGuid,
509 NULL,
510 &HandleCount,
511 &HandleBuffer
512 );
513 if (EFI_ERROR (Status)) {
514 return ;
515 }
516 //
517 // Allocate 4k bytes to hold the ACPI table.
518 //
519 Table = AllocateZeroPool (IBFT_MAX_SIZE);
520 if (Table == NULL) {
521 return ;
522 }
523
524 Heap = (UINT8 *) Table + IBFT_HEAP_OFFSET;
525
526 //
527 // Fill in the various section of the iSCSI Boot Firmware Table.
528 //
529 IScsiInitIbfTableHeader (Table, Rsdt->OemId, &Rsdt->OemTableId);
530 IScsiInitControlSection (Table, HandleCount);
531 IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]);
532 IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer);
533
534 Checksum = CalculateCheckSum8((UINT8 *)Table, Table->Length);
535 Table->Checksum = Checksum;
536
537 FreePool (HandleBuffer);
538
539 //
540 // Install or update the iBFT table.
541 //
542 Status = AcpiTableProtocol->InstallAcpiTable (
543 AcpiTableProtocol,
544 Table,
545 Table->Length,
546 &mTableKey
547 );
548 if (EFI_ERROR(Status)) {
549 return;
550 }
551
552 mIbftInstalled = TRUE;
553 FreePool (Table);
554 }