]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
SecurityPkg OpalPassword: Add solution without SMM device code
[mirror_edk2.git] / SecurityPkg / Tcg / Opal / OpalPassword / OpalPasswordPei.c
1 /** @file
2 Opal Password PEI driver which is used to unlock Opal Password for S3.
3
4 Copyright (c) 2016 - 2018, 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 "OpalPasswordPei.h"
16
17 EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;
18 EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;
19
20 #define OPAL_PCIE_ROOTPORT_SAVESIZE (0x40)
21 #define STORE_INVALID_ROOTPORT_INDEX ((UINT8) -1)
22
23 /**
24 Get IOMMU PPI.
25
26 @return Pointer to IOMMU PPI.
27
28 **/
29 EDKII_IOMMU_PPI *
30 GetIoMmu (
31 VOID
32 )
33 {
34 EFI_STATUS Status;
35 EDKII_IOMMU_PPI *IoMmu;
36
37 IoMmu = NULL;
38 Status = PeiServicesLocatePpi (
39 &gEdkiiIoMmuPpiGuid,
40 0,
41 NULL,
42 (VOID **) &IoMmu
43 );
44 if (!EFI_ERROR (Status) && (IoMmu != NULL)) {
45 return IoMmu;
46 }
47
48 return NULL;
49 }
50
51 /**
52 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
53 OperationBusMasterCommonBuffer64 mapping.
54
55 @param Pages The number of pages to allocate.
56 @param HostAddress A pointer to store the base system memory address of the
57 allocated range.
58 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
59 access the hosts HostAddress.
60 @param Mapping A resulting value to pass to Unmap().
61
62 @retval EFI_SUCCESS The requested memory pages were allocated.
63 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
64 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
65 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
66 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
67
68 **/
69 EFI_STATUS
70 IoMmuAllocateBuffer (
71 IN UINTN Pages,
72 OUT VOID **HostAddress,
73 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
74 OUT VOID **Mapping
75 )
76 {
77 EFI_STATUS Status;
78 UINTN NumberOfBytes;
79 EFI_PHYSICAL_ADDRESS HostPhyAddress;
80 EDKII_IOMMU_PPI *IoMmu;
81
82 *HostAddress = NULL;
83 *DeviceAddress = 0;
84 *Mapping = NULL;
85
86 IoMmu = GetIoMmu ();
87
88 if (IoMmu != NULL) {
89 Status = IoMmu->AllocateBuffer (
90 IoMmu,
91 EfiBootServicesData,
92 Pages,
93 HostAddress,
94 0
95 );
96 if (EFI_ERROR (Status)) {
97 return EFI_OUT_OF_RESOURCES;
98 }
99
100 NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);
101 Status = IoMmu->Map (
102 IoMmu,
103 EdkiiIoMmuOperationBusMasterCommonBuffer,
104 *HostAddress,
105 &NumberOfBytes,
106 DeviceAddress,
107 Mapping
108 );
109 if (EFI_ERROR (Status)) {
110 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
111 *HostAddress = NULL;
112 return EFI_OUT_OF_RESOURCES;
113 }
114 Status = IoMmu->SetAttribute (
115 IoMmu,
116 *Mapping,
117 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
118 );
119 if (EFI_ERROR (Status)) {
120 IoMmu->Unmap (IoMmu, *Mapping);
121 IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);
122 *Mapping = NULL;
123 *HostAddress = NULL;
124 return Status;
125 }
126 } else {
127 Status = PeiServicesAllocatePages (
128 EfiBootServicesData,
129 Pages,
130 &HostPhyAddress
131 );
132 if (EFI_ERROR (Status)) {
133 return EFI_OUT_OF_RESOURCES;
134 }
135 *HostAddress = (VOID *) (UINTN) HostPhyAddress;
136 *DeviceAddress = HostPhyAddress;
137 *Mapping = NULL;
138 }
139 return Status;
140 }
141
142 /**
143 Frees memory that was allocated with AllocateBuffer().
144
145 @param Pages The number of pages to free.
146 @param HostAddress The base system memory address of the allocated range.
147 @param Mapping The mapping value returned from Map().
148
149 **/
150 VOID
151 IoMmuFreeBuffer (
152 IN UINTN Pages,
153 IN VOID *HostAddress,
154 IN VOID *Mapping
155 )
156 {
157 EDKII_IOMMU_PPI *IoMmu;
158
159 IoMmu = GetIoMmu ();
160
161 if (IoMmu != NULL) {
162 IoMmu->SetAttribute (IoMmu, Mapping, 0);
163 IoMmu->Unmap (IoMmu, Mapping);
164 IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);
165 } else {
166 PeiServicesFreePages (
167 (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,
168 Pages
169 );
170 }
171 }
172
173 /**
174 Provide IO action support.
175
176 @param[in] PeiDev The opal device need to perform trusted IO.
177 @param[in] IoType OPAL_IO_TYPE indicating whether to perform a Trusted Send or Trusted Receive.
178 @param[in] SecurityProtocol Security Protocol
179 @param[in] SpSpecific Security Protocol Specific
180 @param[in] TransferLength Transfer Length of Buffer (in bytes) - always a multiple of 512
181 @param[in] Buffer Address of Data to transfer
182
183 @retval EFI_SUCCESS Perform the IO action success.
184 @retval Others Perform the IO action failed.
185
186 **/
187 EFI_STATUS
188 PerformTrustedIo (
189 OPAL_PEI_DEVICE *PeiDev,
190 OPAL_IO_TYPE IoType,
191 UINT8 SecurityProtocol,
192 UINT16 SpSpecific,
193 UINTN TransferLength,
194 VOID *Buffer
195 )
196 {
197 EFI_STATUS Status;
198 UINTN BufferSizeBlocks;
199 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
200 OPAL_DEVICE_ATA *DevInfoAta;
201 AHCI_CONTEXT *AhciContext;
202 NVME_CONTEXT *NvmeContext;
203
204 Status = EFI_DEVICE_ERROR;
205 if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_ATA) {
206 DevInfoAta = (OPAL_DEVICE_ATA *) PeiDev->Device;
207 AhciContext = (AHCI_CONTEXT *) PeiDev->Context;
208
209 BufferSizeBlocks = TransferLength / 512;
210
211 ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );
212 AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ? ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;
213 AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;
214 AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );
215 AtaCommandBlock.AtaFeatures = SecurityProtocol;
216 AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );
217 AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );
218 AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;
219
220
221 ZeroMem( AhciContext->Buffer, HDD_PAYLOAD );
222 ASSERT( TransferLength <= HDD_PAYLOAD );
223
224 if (IoType == OpalSend) {
225 CopyMem( AhciContext->Buffer, Buffer, TransferLength );
226 }
227
228 Status = AhciPioTransfer(
229 AhciContext,
230 (UINT8) DevInfoAta->Port,
231 (UINT8) DevInfoAta->PortMultiplierPort,
232 NULL,
233 0,
234 ( IoType == OpalSend ) ? FALSE : TRUE, // i/o direction
235 &AtaCommandBlock,
236 NULL,
237 AhciContext->Buffer,
238 (UINT32)TransferLength,
239 ATA_TIMEOUT
240 );
241
242 if (IoType == OpalRecv) {
243 CopyMem( Buffer, AhciContext->Buffer, TransferLength );
244 }
245 } else if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
246 NvmeContext = (NVME_CONTEXT *) PeiDev->Context;
247 Status = NvmeSecuritySendReceive (
248 NvmeContext,
249 IoType == OpalSend,
250 SecurityProtocol,
251 SwapBytes16(SpSpecific),
252 TransferLength,
253 Buffer
254 );
255 } else {
256 DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n", PeiDev->DeviceType));
257 }
258
259 return Status;
260 }
261
262 /**
263 Send a security protocol command to a device that receives data and/or the result
264 of one or more commands sent by SendData.
265
266 The ReceiveData function sends a security protocol command to the given MediaId.
267 The security protocol command sent is defined by SecurityProtocolId and contains
268 the security protocol specific data SecurityProtocolSpecificData. The function
269 returns the data from the security protocol command in PayloadBuffer.
270
271 For devices supporting the SCSI command set, the security protocol command is sent
272 using the SECURITY PROTOCOL IN command defined in SPC-4.
273
274 For devices supporting the ATA command set, the security protocol command is sent
275 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
276 is non-zero.
277
278 If the PayloadBufferSize is zero, the security protocol command is sent using the
279 Trusted Non-Data command defined in ATA8-ACS.
280
281 If PayloadBufferSize is too small to store the available data from the security
282 protocol command, the function shall copy PayloadBufferSize bytes into the
283 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
284
285 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
286 the function shall return EFI_INVALID_PARAMETER.
287
288 If the given MediaId does not support security protocol commands, the function shall
289 return EFI_UNSUPPORTED. If there is no media in the device, the function returns
290 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
291 the function returns EFI_MEDIA_CHANGED.
292
293 If the security protocol fails to complete within the Timeout period, the function
294 shall return EFI_TIMEOUT.
295
296 If the security protocol command completes without an error, the function shall
297 return EFI_SUCCESS. If the security protocol command completes with an error, the
298 function shall return EFI_DEVICE_ERROR.
299
300 @param This Indicates a pointer to the calling context.
301 @param MediaId ID of the medium to receive data from.
302 @param Timeout The timeout, in 100ns units, to use for the execution
303 of the security protocol command. A Timeout value of 0
304 means that this function will wait indefinitely for the
305 security protocol command to execute. If Timeout is greater
306 than zero, then this function will return EFI_TIMEOUT
307 if the time required to execute the receive data command
308 is greater than Timeout.
309 @param SecurityProtocolId The value of the "Security Protocol" parameter of
310 the security protocol command to be sent.
311 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
312 of the security protocol command to be sent.
313 @param PayloadBufferSize Size in bytes of the payload data buffer.
314 @param PayloadBuffer A pointer to a destination buffer to store the security
315 protocol command specific payload data for the security
316 protocol command. The caller is responsible for having
317 either implicit or explicit ownership of the buffer.
318 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
319 data written to the payload data buffer.
320
321 @retval EFI_SUCCESS The security protocol command completed successfully.
322 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
323 data from the device. The PayloadBuffer contains the truncated data.
324 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
325 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
326 @retval EFI_NO_MEDIA There is no media in the device.
327 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
328 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
329 PayloadBufferSize is non-zero.
330 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
331 protocol command to execute.
332
333 **/
334 EFI_STATUS
335 EFIAPI
336 SecurityReceiveData (
337 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
338 IN UINT32 MediaId,
339 IN UINT64 Timeout,
340 IN UINT8 SecurityProtocolId,
341 IN UINT16 SecurityProtocolSpecificData,
342 IN UINTN PayloadBufferSize,
343 OUT VOID *PayloadBuffer,
344 OUT UINTN *PayloadTransferSize
345 )
346 {
347 OPAL_PEI_DEVICE *PeiDev;
348
349 PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
350 if (PeiDev == NULL) {
351 return EFI_DEVICE_ERROR;
352 }
353
354 return PerformTrustedIo (
355 PeiDev,
356 OpalRecv,
357 SecurityProtocolId,
358 SecurityProtocolSpecificData,
359 PayloadBufferSize,
360 PayloadBuffer
361 );
362 }
363
364 /**
365 Send a security protocol command to a device.
366
367 The SendData function sends a security protocol command containing the payload
368 PayloadBuffer to the given MediaId. The security protocol command sent is
369 defined by SecurityProtocolId and contains the security protocol specific data
370 SecurityProtocolSpecificData. If the underlying protocol command requires a
371 specific padding for the command payload, the SendData function shall add padding
372 bytes to the command payload to satisfy the padding requirements.
373
374 For devices supporting the SCSI command set, the security protocol command is sent
375 using the SECURITY PROTOCOL OUT command defined in SPC-4.
376
377 For devices supporting the ATA command set, the security protocol command is sent
378 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
379 is non-zero. If the PayloadBufferSize is zero, the security protocol command is
380 sent using the Trusted Non-Data command defined in ATA8-ACS.
381
382 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
383 return EFI_INVALID_PARAMETER.
384
385 If the given MediaId does not support security protocol commands, the function
386 shall return EFI_UNSUPPORTED. If there is no media in the device, the function
387 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
388 device, the function returns EFI_MEDIA_CHANGED.
389
390 If the security protocol fails to complete within the Timeout period, the function
391 shall return EFI_TIMEOUT.
392
393 If the security protocol command completes without an error, the function shall return
394 EFI_SUCCESS. If the security protocol command completes with an error, the function
395 shall return EFI_DEVICE_ERROR.
396
397 @param This Indicates a pointer to the calling context.
398 @param MediaId ID of the medium to receive data from.
399 @param Timeout The timeout, in 100ns units, to use for the execution
400 of the security protocol command. A Timeout value of 0
401 means that this function will wait indefinitely for the
402 security protocol command to execute. If Timeout is greater
403 than zero, then this function will return EFI_TIMEOUT
404 if the time required to execute the send data command
405 is greater than Timeout.
406 @param SecurityProtocolId The value of the "Security Protocol" parameter of
407 the security protocol command to be sent.
408 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
409 of the security protocol command to be sent.
410 @param PayloadBufferSize Size in bytes of the payload data buffer.
411 @param PayloadBuffer A pointer to a destination buffer to store the security
412 protocol command specific payload data for the security
413 protocol command.
414
415 @retval EFI_SUCCESS The security protocol command completed successfully.
416 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
417 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
418 @retval EFI_NO_MEDIA There is no media in the device.
419 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
420 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
421 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
422 protocol command to execute.
423
424 **/
425 EFI_STATUS
426 EFIAPI
427 SecuritySendData (
428 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
429 IN UINT32 MediaId,
430 IN UINT64 Timeout,
431 IN UINT8 SecurityProtocolId,
432 IN UINT16 SecurityProtocolSpecificData,
433 IN UINTN PayloadBufferSize,
434 IN VOID *PayloadBuffer
435 )
436 {
437 OPAL_PEI_DEVICE *PeiDev;
438
439 PeiDev = OPAL_PEI_DEVICE_FROM_THIS (This);
440 if (PeiDev == NULL) {
441 return EFI_DEVICE_ERROR;
442 }
443
444 return PerformTrustedIo (
445 PeiDev,
446 OpalSend,
447 SecurityProtocolId,
448 SecurityProtocolSpecificData,
449 PayloadBufferSize,
450 PayloadBuffer
451 );
452
453 }
454
455 /**
456 Save/Restore RootPort configuration space.
457
458 @param[in] DevInfoNvme Pointer to NVMe device info.
459 @param[in] SaveAction TRUE: Save, FALSE: Restore
460 @param[in,out] PcieConfBufferList Configuration space data buffer for save/restore
461
462 @return PCIE base address of this RootPort
463 **/
464 UINTN
465 SaveRestoreRootportConfSpace (
466 IN OPAL_DEVICE_NVME *DevInfoNvme,
467 IN BOOLEAN SaveAction,
468 IN OUT UINT8 **PcieConfBufferList
469 )
470 {
471 UINTN RpBase;
472 UINTN Length;
473 OPAL_PCI_DEVICE *DevNode;
474 UINT8 *StorePcieConfData;
475 UINTN Index;
476
477 Length = 0;
478 Index = 0;
479 RpBase = 0;
480
481 while (sizeof (OPAL_DEVICE_NVME) + Length < DevInfoNvme->Length) {
482 DevNode = (OPAL_PCI_DEVICE *)((UINT8*)DevInfoNvme->PciBridgeNode + Length);
483 RpBase = PCI_LIB_ADDRESS (DevNode->Bus, DevNode->Device, DevNode->Function, 0x0);
484
485 if (PcieConfBufferList != NULL) {
486 if (SaveAction) {
487 StorePcieConfData = (UINT8 *) AllocateZeroPool (OPAL_PCIE_ROOTPORT_SAVESIZE);
488 ASSERT (StorePcieConfData != NULL);
489 OpalPciRead (StorePcieConfData, RpBase, OPAL_PCIE_ROOTPORT_SAVESIZE);
490 PcieConfBufferList[Index] = StorePcieConfData;
491 } else {
492 // Skip PCIe Command & Status registers
493 StorePcieConfData = PcieConfBufferList[Index];
494 OpalPciWrite (RpBase, StorePcieConfData, 4);
495 OpalPciWrite (RpBase + 8, StorePcieConfData + 8, OPAL_PCIE_ROOTPORT_SAVESIZE - 8);
496
497 FreePool (StorePcieConfData);
498 }
499 }
500
501 Length += sizeof (OPAL_PCI_DEVICE);
502 Index ++;
503 }
504
505 return RpBase;
506 }
507
508 /**
509 Configure RootPort for downstream PCIe NAND devices.
510
511 @param[in] RpBase - PCIe configuration space address of this RootPort
512 @param[in] BusNumber - Bus number
513 @param[in] MemoryBase - Memory base address
514 @param[in] MemoryLength - Memory size
515
516 **/
517 VOID
518 ConfigureRootPortForPcieNand (
519 IN UINTN RpBase,
520 IN UINTN BusNumber,
521 IN UINT32 MemoryBase,
522 IN UINT32 MemoryLength
523 )
524 {
525 UINT32 MemoryLimit;
526
527 DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n",
528 BusNumber, MemoryBase, MemoryLength));
529
530 if (MemoryLength == 0) {
531 MemoryLimit = MemoryBase;
532 } else {
533 MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M
534 }
535
536 ///
537 /// Configue PCIE configuration space for RootPort
538 ///
539 PciWrite8 (RpBase + NVME_PCIE_BNUM + 1, (UINT8) BusNumber); // Secondary Bus Number registers
540 PciWrite8 (RpBase + NVME_PCIE_BNUM + 2, (UINT8) BusNumber); // Subordinate Bus Number registers
541 PciWrite8 (RpBase + NVME_PCIE_IOBL, 0xFF); // I/O Base registers
542 PciWrite8 (RpBase + NVME_PCIE_IOBL + 1, 0x00); // I/O Limit registers
543 PciWrite16 (RpBase + NVME_PCIE_MBL, (UINT16) RShiftU64 ((UINTN)MemoryBase, 16)); // Memory Base register
544 PciWrite16 (RpBase + NVME_PCIE_MBL + 2, (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register
545 PciWrite16 (RpBase + NVME_PCIE_PMBL, 0xFFFF); // Prefetchable Memory Base registers
546 PciWrite16 (RpBase + NVME_PCIE_PMBL + 2, 0x0000); // Prefetchable Memory Limit registers
547 PciWrite32 (RpBase + NVME_PCIE_PMBU32, 0xFFFFFFFF); // Prefetchable Memory Upper Base registers
548 PciWrite32 (RpBase + NVME_PCIE_PMLU32, 0x00000000); // Prefetchable Memory Upper Limit registers
549 }
550
551 /**
552
553 The function returns whether or not the device is Opal Locked.
554 TRUE means that the device is partially or fully locked.
555 This will perform a Level 0 Discovery and parse the locking feature descriptor
556
557 @param[in] OpalDev Opal object to determine if locked.
558 @param[out] BlockSidSupported Whether device support BlockSid feature.
559
560 **/
561 BOOLEAN
562 IsOpalDeviceLocked(
563 OPAL_PEI_DEVICE *OpalDev,
564 BOOLEAN *BlockSidSupported
565 )
566 {
567 OPAL_SESSION Session;
568 OPAL_DISK_SUPPORT_ATTRIBUTE SupportedAttributes;
569 TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature;
570 UINT16 OpalBaseComId;
571 TCG_RESULT Ret;
572
573 Session.Sscp = &OpalDev->Sscp;
574 Session.MediaId = 0;
575
576 Ret = OpalGetSupportedAttributesInfo (&Session, &SupportedAttributes, &OpalBaseComId);
577 if (Ret != TcgResultSuccess) {
578 return FALSE;
579 }
580
581 Session.OpalBaseComId = OpalBaseComId;
582 *BlockSidSupported = SupportedAttributes.BlockSid == 1 ? TRUE : FALSE;
583
584 Ret = OpalGetLockingInfo(&Session, &LockingFeature);
585 if (Ret != TcgResultSuccess) {
586 return FALSE;
587 }
588
589 return OpalDeviceLocked (&SupportedAttributes, &LockingFeature);
590 }
591
592 /**
593 Unlock OPAL password for S3.
594
595 @param[in] OpalDev Opal object to unlock.
596
597 **/
598 VOID
599 UnlockOpalPassword (
600 IN OPAL_PEI_DEVICE *OpalDev
601 )
602 {
603 TCG_RESULT Result;
604 OPAL_SESSION Session;
605 BOOLEAN BlockSidSupport;
606 UINT32 PpStorageFlags;
607 BOOLEAN BlockSIDEnabled;
608
609 BlockSidSupport = FALSE;
610 if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {
611 ZeroMem(&Session, sizeof (Session));
612 Session.Sscp = &OpalDev->Sscp;
613 Session.MediaId = 0;
614 Session.OpalBaseComId = OpalDev->Device->OpalBaseComId;
615
616 Result = OpalUtilUpdateGlobalLockingRange (
617 &Session,
618 OpalDev->Device->Password,
619 OpalDev->Device->PasswordLength,
620 FALSE,
621 FALSE
622 );
623 DEBUG ((
624 DEBUG_INFO,
625 "%a() OpalUtilUpdateGlobalLockingRange() Result = 0x%x\n",
626 __FUNCTION__,
627 Result
628 ));
629 }
630
631 PpStorageFlags = Tcg2PhysicalPresenceLibGetManagementFlags ();
632 if ((PpStorageFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
633 BlockSIDEnabled = TRUE;
634 } else {
635 BlockSIDEnabled = FALSE;
636 }
637 if (BlockSIDEnabled && BlockSidSupport) {
638 ZeroMem(&Session, sizeof (Session));
639 Session.Sscp = &OpalDev->Sscp;
640 Session.MediaId = 0;
641 Session.OpalBaseComId = OpalDev->Device->OpalBaseComId;
642 Result = OpalBlockSid (&Session, TRUE);
643 DEBUG ((
644 DEBUG_INFO,
645 "%a() OpalBlockSid() Result = 0x%x\n",
646 __FUNCTION__,
647 Result
648 ));
649 }
650 }
651
652 /**
653 Unlock ATA OPAL password for S3.
654
655 **/
656 VOID
657 UnlockOpalPasswordAta (
658 VOID
659 )
660 {
661 EFI_STATUS Status;
662 UINT8 *DevInfo;
663 OPAL_DEVICE_ATA TempDevInfoAta;
664 OPAL_DEVICE_ATA *DevInfoAta;
665 UINTN DevInfoLengthAta;
666 UINT8 Bus;
667 UINT8 Device;
668 UINT8 Function;
669 OPAL_PEI_DEVICE OpalDev;
670 UINT8 BaseClassCode;
671 UINT8 SubClassCode;
672 UINT8 SataCmdSt;
673 AHCI_CONTEXT AhciContext;
674 UINT32 AhciBar;
675
676 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
677
678 //
679 // Get ATA OPAL device info from LockBox.
680 //
681 DevInfo = (UINT8 *) &TempDevInfoAta;
682 DevInfoLengthAta = sizeof (OPAL_DEVICE_ATA);
683 Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);
684 if (Status == EFI_BUFFER_TOO_SMALL) {
685 DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthAta));
686 if (DevInfo != NULL) {
687 Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);
688 }
689 }
690 if (EFI_ERROR (Status) || (DevInfo == NULL)) {
691 return;
692 }
693
694 for (DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;
695 (UINTN) DevInfoAta < ((UINTN) DevInfo + DevInfoLengthAta);
696 DevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) DevInfoAta + DevInfoAta->Length)) {
697 Bus = DevInfoAta->Device.Bus;
698 Device = DevInfoAta->Device.Device;
699 Function = DevInfoAta->Device.Function;
700
701 SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET));
702 PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), 0x6);
703
704 BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
705 SubClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
706 if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
707 ((SubClassCode != PCI_CLASS_MASS_STORAGE_SATADPA) && (SubClassCode != PCI_CLASS_MASS_STORAGE_RAID))) {
708 DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode are not supported\n", __FUNCTION__));
709 } else {
710 AhciBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));
711 PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), DevInfoAta->BarAddr);
712
713 ZeroMem (&AhciContext, sizeof (AHCI_CONTEXT));
714 AhciContext.AhciBar = DevInfoAta->BarAddr;
715 AhciAllocateResource (&AhciContext);
716 Status = AhciModeInitialize (&AhciContext, (UINT8)DevInfoAta->Port);
717 ASSERT_EFI_ERROR (Status);
718 if (EFI_ERROR (Status)) {
719 DEBUG ((DEBUG_ERROR, "%a() AhciModeInitialize() error, Status: %r\n", __FUNCTION__, Status));
720 }
721
722 OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
723 OpalDev.Sscp.ReceiveData = SecurityReceiveData;
724 OpalDev.Sscp.SendData = SecuritySendData;
725 OpalDev.DeviceType = OPAL_DEVICE_TYPE_ATA;
726 OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoAta;
727 OpalDev.Context = &AhciContext;
728
729 UnlockOpalPassword (&OpalDev);
730
731 AhciFreeResource (&AhciContext);
732 PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), AhciBar);
733 }
734 PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), SataCmdSt);
735 }
736
737 ZeroMem (DevInfo, DevInfoLengthAta);
738 if ((UINTN) DevInfo != (UINTN) &TempDevInfoAta) {
739 FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthAta));
740 }
741
742 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
743 }
744
745 /**
746 Unlock NVMe OPAL password for S3.
747
748 **/
749 VOID
750 UnlockOpalPasswordNvme (
751 VOID
752 )
753 {
754 EFI_STATUS Status;
755 UINT8 *DevInfo;
756 OPAL_DEVICE_NVME TempDevInfoNvme;
757 OPAL_DEVICE_NVME *DevInfoNvme;
758 UINTN DevInfoLengthNvme;
759 UINT8 Bus;
760 UINT8 Device;
761 UINT8 Function;
762 OPAL_PEI_DEVICE OpalDev;
763 UINT8 BaseClassCode;
764 UINT8 SubClassCode;
765 UINT8 ProgInt;
766 UINT8 NvmeCmdSt;
767 UINT8 *StorePcieConfDataList[16];
768 UINTN RpBase;
769 UINTN MemoryBase;
770 UINTN MemoryLength;
771 NVME_CONTEXT NvmeContext;
772
773 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
774
775 //
776 // Get NVMe OPAL device info from LockBox.
777 //
778 DevInfo = (UINT8 *) &TempDevInfoNvme;
779 DevInfoLengthNvme = sizeof (OPAL_DEVICE_NVME);
780 Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);
781 if (Status == EFI_BUFFER_TOO_SMALL) {
782 DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
783 if (DevInfo != NULL) {
784 Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);
785 }
786 }
787 if (EFI_ERROR (Status) || (DevInfo == NULL)) {
788 return;
789 }
790
791 for (DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;
792 (UINTN) DevInfoNvme < ((UINTN) DevInfo + DevInfoLengthNvme);
793 DevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) DevInfoNvme + DevInfoNvme->Length)) {
794 Bus = DevInfoNvme->Device.Bus;
795 Device = DevInfoNvme->Device.Device;
796 Function = DevInfoNvme->Device.Function;
797
798 RpBase = 0;
799 NvmeCmdSt = 0;
800
801 ///
802 /// Save original RootPort configuration space to heap
803 ///
804 RpBase = SaveRestoreRootportConfSpace (
805 DevInfoNvme,
806 TRUE, // save
807 StorePcieConfDataList
808 );
809 MemoryBase = DevInfoNvme->BarAddr;
810 MemoryLength = 0;
811 ConfigureRootPortForPcieNand (RpBase, Bus, (UINT32) MemoryBase, (UINT32) MemoryLength);
812
813 ///
814 /// Enable PCIE decode for RootPort
815 ///
816 NvmeCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
817 PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0x6);
818
819 BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
820 SubClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
821 ProgInt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x09));
822 if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||
823 (SubClassCode != PCI_CLASS_MASS_STORAGE_NVM) ||
824 (ProgInt != PCI_IF_NVMHCI)) {
825 DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode/PI are not supported\n", __FUNCTION__));
826 } else {
827 ZeroMem (&NvmeContext, sizeof (NVME_CONTEXT));
828 NvmeContext.Nbar = DevInfoNvme->BarAddr;
829 NvmeContext.PciBase = PCI_LIB_ADDRESS (Bus, Device, Function, 0x0);
830 NvmeContext.NvmeInitWaitTime = 0;
831 NvmeContext.Nsid = DevInfoNvme->NvmeNamespaceId;
832 NvmeAllocateResource (&NvmeContext);
833 Status = NvmeControllerInit (&NvmeContext);
834
835 OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;
836 OpalDev.Sscp.ReceiveData = SecurityReceiveData;
837 OpalDev.Sscp.SendData = SecuritySendData;
838 OpalDev.DeviceType = OPAL_DEVICE_TYPE_NVME;
839 OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoNvme;
840 OpalDev.Context = &NvmeContext;
841
842 UnlockOpalPassword (&OpalDev);
843
844 Status = NvmeControllerExit (&NvmeContext);
845 NvmeFreeResource (&NvmeContext);
846 }
847
848 ASSERT (RpBase != 0);
849 PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0);
850 RpBase = SaveRestoreRootportConfSpace (
851 DevInfoNvme,
852 FALSE, // restore
853 StorePcieConfDataList
854 );
855 PciWrite8 (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);
856 }
857
858 ZeroMem (DevInfo, DevInfoLengthNvme);
859 if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {
860 FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));
861 }
862
863 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
864 }
865
866 /**
867 Unlock OPAL password for S3.
868
869 **/
870 VOID
871 OpalPasswordS3 (
872 VOID
873 )
874 {
875 UnlockOpalPasswordAta ();
876 UnlockOpalPasswordNvme ();
877 }
878
879 /**
880 Entry point of the notification callback function itself within the PEIM.
881 It is to unlock OPAL password for S3.
882
883 @param PeiServices Indirect reference to the PEI Services Table.
884 @param NotifyDescriptor Address of the notification descriptor data structure.
885 @param Ppi Address of the PPI that was installed.
886
887 @return Status of the notification.
888 The status code returned from this function is ignored.
889 **/
890 EFI_STATUS
891 EFIAPI
892 OpalPasswordEndOfPeiNotify(
893 IN EFI_PEI_SERVICES **PeiServices,
894 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
895 IN VOID *Ppi
896 )
897 {
898 EFI_STATUS Status;
899 EFI_BOOT_MODE BootMode;
900
901 Status = PeiServicesGetBootMode (&BootMode);
902 ASSERT_EFI_ERROR (Status);
903 if (BootMode != BOOT_ON_S3_RESUME) {
904 return EFI_UNSUPPORTED;
905 }
906
907 DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));
908
909 OpalPasswordS3 ();
910
911 DEBUG ((DEBUG_INFO, "%a() - exit at S3 resume\n", __FUNCTION__));
912
913 return EFI_SUCCESS;
914 }
915
916 EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordEndOfPeiNotifyDesc = {
917 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
918 &gEfiEndOfPeiSignalPpiGuid,
919 OpalPasswordEndOfPeiNotify
920 };
921
922 /**
923 Main entry for this module.
924
925 @param FileHandle Handle of the file being invoked.
926 @param PeiServices Pointer to PEI Services table.
927
928 @return Status from PeiServicesNotifyPpi.
929
930 **/
931 EFI_STATUS
932 EFIAPI
933 OpalPasswordPeiInit (
934 IN EFI_PEI_FILE_HANDLE FileHandle,
935 IN CONST EFI_PEI_SERVICES **PeiServices
936 )
937 {
938 EFI_STATUS Status;
939
940 Status = PeiServicesNotifyPpi (&mOpalPasswordEndOfPeiNotifyDesc);
941 ASSERT_EFI_ERROR (Status);
942 return Status;
943 }
944