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