]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c
SecurityPkg OpalPasswordSmm: Always execute BlockSid command.
[mirror_edk2.git] / SecurityPkg / Tcg / Opal / OpalPasswordSmm / OpalPasswordSmm.c
1 /** @file
2 Opal password smm driver which is used to support Opal security feature at s3 path.
3
4 Copyright (c) 2016, 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 "OpalPasswordSmm.h"
16
17 #define SMM_SIZE_ALLOC_BYTES (512)
18 #define RESPONSE_SIZE (200)
19
20 #define PCI_CLASS_MASS_STORAGE_AHCI (0x06)
21
22 #define OPAL_PCIE_ROOTPORT_SAVESIZE (0x40)
23 #define STORE_INVALID_ROOTPORT_INDEX ((UINT8) -1)
24 #define OPAL_DEVICE_TYPE_SATA 0x1
25 #define OPAL_DEVICE_TYPE_NVME 0x2
26 #define OPAL_DEVICE_TYPE_UNKNOWN 0xFF
27
28 //
29 // To unlock the Intel SATA controller at S3 Resume, restored the following registers.
30 //
31 const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {
32 {0x9, S3BootScriptWidthUint8},
33 {0x10, S3BootScriptWidthUint32},
34 {0x14, S3BootScriptWidthUint32},
35 {0x18, S3BootScriptWidthUint32},
36 {0x1C, S3BootScriptWidthUint32},
37 {0x20, S3BootScriptWidthUint32},
38 {0x24, S3BootScriptWidthUint32},
39 {0x3c, S3BootScriptWidthUint8},
40 {0x3d, S3BootScriptWidthUint8},
41 {0x40, S3BootScriptWidthUint16},
42 {0x42, S3BootScriptWidthUint16},
43 {0x92, S3BootScriptWidthUint16},
44 {0x94, S3BootScriptWidthUint32},
45 {0x9C, S3BootScriptWidthUint32},
46 {0x4, S3BootScriptWidthUint16},
47 };
48
49
50 UINT8 mSwSmiValue;
51 LIST_ENTRY *mOpalDeviceList;
52 LIST_ENTRY mSmmDeviceList = INITIALIZE_LIST_HEAD_VARIABLE (mSmmDeviceList);
53
54 BOOLEAN mSendBlockSID = FALSE;
55
56 // AHCI
57 UINT32 mAhciBar = 0;
58 EFI_AHCI_REGISTERS mAhciRegisters;
59 VOID *mBuffer = NULL; // DMA can not read/write Data to smram, so we pre-allocates Buffer from AcpiNVS.
60 //
61 // NVME
62 NVME_CONTEXT mNvmeContext;
63
64 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mGcdMemSpace = NULL;
65 UINTN mNumberOfDescriptors = 0;
66
67 /**
68 Add new bridge node or nvme device info to the device list.
69
70 @param[in] BusNum The bus number.
71 @param[in] DevNum The device number.
72 @param[in] FuncNum The function number.
73 @param[in] Dev The device which need to add device node info.
74
75 **/
76 VOID
77 AddPciDeviceNode (
78 UINT32 BusNum,
79 UINT32 DevNum,
80 UINT32 FuncNum,
81 OPAL_SMM_DEVICE *Dev
82 )
83 {
84 UINT8 *DevList;
85 PCI_DEVICE *DeviceNode;
86
87 DevList = AllocateZeroPool (sizeof (PCI_DEVICE) + Dev->Length);
88 ASSERT (DevList != NULL);
89
90 if (Dev->Length != 0) {
91 CopyMem (DevList, Dev->PciBridgeNode, Dev->Length);
92 FreePool (Dev->PciBridgeNode);
93 }
94
95 DeviceNode = (PCI_DEVICE *) (DevList + Dev->Length);
96
97 DeviceNode->BusNum = BusNum;
98 DeviceNode->DevNum = DevNum;
99 DeviceNode->FuncNum = FuncNum;
100
101 Dev->Length += sizeof (PCI_DEVICE);
102 Dev->PciBridgeNode = (PCI_DEVICE *)DevList;
103 }
104
105 /**
106 Extract device info from the input device path.
107
108 @param[in] DevicePath Device path info for the device.
109 @param[in,out] Dev The device which new inputed.
110
111 **/
112 VOID
113 ExtractDeviceInfoFromDevicePath (
114 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
115 IN OUT OPAL_SMM_DEVICE *Dev
116 )
117 {
118 EFI_DEVICE_PATH_PROTOCOL *TmpDevPath;
119 EFI_DEVICE_PATH_PROTOCOL *TmpDevPath2;
120 PCI_DEVICE_PATH *PciDevPath;
121 SATA_DEVICE_PATH *SataDevPath;
122 NVME_NAMESPACE_DEVICE_PATH *NvmeDevPath;
123 UINTN BusNum;
124
125 TmpDevPath = DevicePath;
126 Dev->DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;
127
128 while (!IsDevicePathEnd(TmpDevPath)) {
129 if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_SATA_DP) {
130 //
131 // SATA
132 //
133 SataDevPath = ( SATA_DEVICE_PATH* )TmpDevPath;
134 Dev->SataPort = SataDevPath->HBAPortNumber;
135 Dev->SataPortMultiplierPort = SataDevPath->PortMultiplierPortNumber;
136 Dev->DeviceType = OPAL_DEVICE_TYPE_SATA;
137 break;
138 } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {
139 //
140 // NVMe
141 //
142 NvmeDevPath = ( NVME_NAMESPACE_DEVICE_PATH* )TmpDevPath;
143 Dev->NvmeNamespaceId = NvmeDevPath->NamespaceId;
144 Dev->DeviceType = OPAL_DEVICE_TYPE_NVME;
145 break;
146 }
147 TmpDevPath = NextDevicePathNode (TmpDevPath);
148 }
149
150 //
151 // Get bridge node info for the nvme device.
152 //
153 BusNum = 0;
154 TmpDevPath = DevicePath;
155 TmpDevPath2 = NextDevicePathNode (DevicePath);
156 while (!IsDevicePathEnd(TmpDevPath2)) {
157 if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {
158 PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;
159 if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||
160 (TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_SATA_DP)) {
161 Dev->BusNum = (UINT32)BusNum;
162 Dev->DevNum = PciDevPath->Device;
163 Dev->FuncNum = PciDevPath->Function;
164 } else {
165 AddPciDeviceNode((UINT32)BusNum, PciDevPath->Device, PciDevPath->Function, Dev);
166 if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {
167 BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, NVME_PCIE_SEC_BNUM));
168 }
169 }
170 }
171
172 TmpDevPath = NextDevicePathNode (TmpDevPath);
173 TmpDevPath2 = NextDevicePathNode (TmpDevPath2);
174 }
175 }
176
177 /**
178
179 The function returns whether or not the device is Opal Locked.
180 TRUE means that the device is partially or fully locked.
181 This will perform a Level 0 Discovery and parse the locking feature descriptor
182
183 @param[in] OpalDev Opal object to determine if locked
184 @param[out] BlockSidSupported Whether device support BlockSid feature.
185
186 **/
187 BOOLEAN
188 IsOpalDeviceLocked(
189 OPAL_SMM_DEVICE *OpalDev,
190 BOOLEAN *BlockSidSupported
191 )
192 {
193 OPAL_SESSION Session;
194 OPAL_DISK_SUPPORT_ATTRIBUTE SupportedAttributes;
195 TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature;
196 UINT16 OpalBaseComId;
197 TCG_RESULT Ret;
198
199 Session.Sscp = &OpalDev->Sscp;
200 Session.MediaId = 0;
201
202 Ret = OpalGetSupportedAttributesInfo (&Session, &SupportedAttributes, &OpalBaseComId);
203 if (Ret != TcgResultSuccess) {
204 return FALSE;
205 }
206
207 OpalDev->OpalBaseComId = OpalBaseComId;
208 Session.OpalBaseComId = OpalBaseComId;
209 *BlockSidSupported = SupportedAttributes.BlockSid == 1 ? TRUE : FALSE;
210
211 Ret = OpalGetLockingInfo(&Session, &LockingFeature);
212 if (Ret != TcgResultSuccess) {
213 return FALSE;
214 }
215
216 return OpalDeviceLocked (&SupportedAttributes, &LockingFeature);
217 }
218
219 /**
220 Save/Restore RootPort configuration space.
221
222 @param[in] DeviceNode - The device node.
223 @param[in] SaveAction - TRUE: Save, FALSE: Restore
224 @param[in,out] PcieConfBufferList - Configuration space data buffer for save/restore
225
226 @retval - PCIE base address of this RootPort
227 **/
228 UINTN
229 SaveRestoreRootportConfSpace (
230 IN OPAL_SMM_DEVICE *DeviceNode,
231 IN BOOLEAN SaveAction,
232 IN OUT UINT8 **PcieConfBufferList
233 )
234 {
235 UINTN RpBase;
236 UINTN Length;
237 PCI_DEVICE *DevNode;
238 UINT8 *StorePcieConfData;
239 UINTN Index;
240
241 Length = 0;
242 Index = 0;
243 RpBase = 0;
244
245 while (Length < DeviceNode->Length) {
246 DevNode = (PCI_DEVICE *)((UINT8*)DeviceNode->PciBridgeNode + Length);
247 RpBase = PCI_LIB_ADDRESS (DevNode->BusNum, DevNode->DevNum, DevNode->FuncNum, 0x0);
248
249 if (PcieConfBufferList != NULL) {
250 if (SaveAction) {
251 StorePcieConfData = (UINT8 *) AllocateZeroPool (OPAL_PCIE_ROOTPORT_SAVESIZE);
252 ASSERT (StorePcieConfData != NULL);
253 OpalPciRead (StorePcieConfData, RpBase, OPAL_PCIE_ROOTPORT_SAVESIZE);
254 PcieConfBufferList[Index] = StorePcieConfData;
255 } else {
256 // Skip PCIe Command & Status registers
257 StorePcieConfData = PcieConfBufferList[Index];
258 OpalPciWrite (RpBase, StorePcieConfData, 4);
259 OpalPciWrite (RpBase + 8, StorePcieConfData + 8, OPAL_PCIE_ROOTPORT_SAVESIZE - 8);
260
261 FreePool (StorePcieConfData);
262 }
263 }
264
265 Length += sizeof (PCI_DEVICE);
266 Index ++;
267 }
268
269 return RpBase;
270 }
271
272 /**
273 Configure RootPort for downstream PCIe NAND devices.
274
275 @param[in] RpBase - PCIe configuration space address of this RootPort
276 @param[in] BusNumber - Bus number
277 @param[in] MemoryBase - Memory base address
278 @param[in] MemoryLength - Memory size
279
280 **/
281 VOID
282 ConfigureRootPortForPcieNand (
283 IN UINTN RpBase,
284 IN UINTN BusNumber,
285 IN UINT32 MemoryBase,
286 IN UINT32 MemoryLength
287 )
288 {
289 UINT32 MemoryLimit;
290
291 DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n",
292 BusNumber, MemoryBase, MemoryLength));
293
294 if (MemoryLength == 0) {
295 MemoryLimit = MemoryBase;
296 } else {
297 MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M
298 }
299
300 ///
301 /// Configue PCIE configuration space for RootPort
302 ///
303 PciWrite8 (RpBase + NVME_PCIE_BNUM + 1, (UINT8) BusNumber); // Secondary Bus Number registers
304 PciWrite8 (RpBase + NVME_PCIE_BNUM + 2, (UINT8) BusNumber); // Subordinate Bus Number registers
305 PciWrite8 (RpBase + NVME_PCIE_IOBL, 0xFF); // I/O Base registers
306 PciWrite8 (RpBase + NVME_PCIE_IOBL + 1, 0x00); // I/O Limit registers
307 PciWrite16 (RpBase + NVME_PCIE_MBL, (UINT16) RShiftU64 ((UINTN)MemoryBase, 16)); // Memory Base register
308 PciWrite16 (RpBase + NVME_PCIE_MBL + 2, (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register
309 PciWrite16 (RpBase + NVME_PCIE_PMBL, 0xFFFF); // Prefetchable Memory Base registers
310 PciWrite16 (RpBase + NVME_PCIE_PMBL + 2, 0x0000); // Prefetchable Memory Limit registers
311 PciWrite32 (RpBase + NVME_PCIE_PMBU32, 0xFFFFFFFF); // Prefetchable Memory Upper Base registers
312 PciWrite32 (RpBase + NVME_PCIE_PMLU32, 0x00000000); // Prefetchable Memory Upper Limit registers
313 }
314
315
316 /**
317 Dispatch function for a Software SMI handler.
318
319 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
320 @param[in] RegisterContext Points to an optional handler context which was specified when the
321 handler was registered.
322 @param[in, out] CommBuffer A pointer to a collection of Data in memory that will
323 be conveyed from a non-SMM environment into an SMM environment.
324 @param[in, out] CommBufferSize The Size of the CommBuffer.
325
326 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
327 should still be called.
328 @retval Others Other execution results.
329 **/
330 EFI_STATUS
331 EFIAPI
332 SmmUnlockOpalPassword (
333 IN EFI_HANDLE DispatchHandle,
334 IN CONST VOID *RegisterContext,
335 IN OUT VOID *CommBuffer,
336 IN OUT UINTN *CommBufferSize
337 )
338 {
339 EFI_STATUS Status;
340 OPAL_SMM_DEVICE *OpalDev;
341 LIST_ENTRY *Entry;
342 UINT8 BaseClassCode;
343 UINT8 SubClassCode;
344 UINT8 ProgInt;
345 TCG_RESULT Result;
346 UINT8 SataCmdSt;
347 UINT8 *StorePcieConfDataList[16];
348 UINTN RpBase;
349 UINTN MemoryBase;
350 UINTN MemoryLength;
351 OPAL_SESSION Session;
352 BOOLEAN BlockSidSupport;
353
354 ZeroMem (StorePcieConfDataList, sizeof (StorePcieConfDataList));
355 Status = EFI_DEVICE_ERROR;
356
357 //
358 // try to unlock all locked hdd disks.
359 //
360 for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) {
361 OpalDev = BASE_CR(Entry, OPAL_SMM_DEVICE, Link);
362
363 RpBase = 0;
364 SataCmdSt = 0;
365
366 ///
367 /// Configure RootPort for PCIe AHCI/NVME devices.
368 ///
369 if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
370 ///
371 /// Save original RootPort configuration space to heap
372 ///
373 RpBase = SaveRestoreRootportConfSpace (
374 OpalDev,
375 TRUE,
376 StorePcieConfDataList
377 );
378 MemoryBase = mNvmeContext.Nbar;
379 MemoryLength = 0;
380 ConfigureRootPortForPcieNand (RpBase, OpalDev->BusNum, (UINT32) MemoryBase, (UINT32) MemoryLength);
381
382 ///
383 /// Enable PCIE decode for RootPort
384 ///
385 SataCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);
386 PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0x6);
387 } else {
388 SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD));
389 PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), 0x6);
390 }
391
392 BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0B));
393 SubClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0A));
394 ProgInt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x09));
395 if (BaseClassCode != PCI_CLASS_MASS_STORAGE) {
396 Status = EFI_INVALID_PARAMETER;
397 break;
398 }
399
400 Status = EFI_DEVICE_ERROR;
401 if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_SATA) {
402 if ((SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) || (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID)) {
403 Status = GetAhciBaseAddress (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum);
404 if (EFI_ERROR (Status)) {
405 DEBUG ((DEBUG_ERROR, "GetAhciBaseAddress error, Status: %r\n", Status));
406 goto done;
407 }
408 Status = AhciModeInitialize ((UINT8)OpalDev->SataPort);
409 ASSERT_EFI_ERROR (Status);
410 if (EFI_ERROR (Status)) {
411 DEBUG ((DEBUG_ERROR, "AhciModeInitialize error, Status: %r\n", Status));
412 goto done;
413 }
414 } else {
415 DEBUG ((DEBUG_ERROR, "SubClassCode not support for SATA device\n"));
416 }
417 } else if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
418 if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {
419 if (ProgInt != PCI_IF_NVMHCI) {
420 DEBUG ((DEBUG_ERROR, "PI not support, skipped\n"));
421 Status = EFI_NOT_FOUND;
422 goto done;
423 }
424
425 mNvmeContext.PciBase = PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0);
426 mNvmeContext.NvmeInitWaitTime = 0;
427 mNvmeContext.Nsid = OpalDev->NvmeNamespaceId;
428 Status = NvmeControllerInit (&mNvmeContext);
429 } else {
430 DEBUG ((DEBUG_ERROR, "SubClassCode not support for NVME device\n"));
431 }
432 } else {
433 DEBUG ((DEBUG_ERROR, "Invalid Devicetype\n"));
434 goto done;
435 }
436
437 Status = EFI_DEVICE_ERROR;
438 BlockSidSupport = FALSE;
439 if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {
440 ZeroMem(&Session, sizeof(Session));
441 Session.Sscp = &OpalDev->Sscp;
442 Session.MediaId = 0;
443 Session.OpalBaseComId = OpalDev->OpalBaseComId;
444
445 Result = OpalSupportUnlock (&Session, OpalDev->Password, OpalDev->PasswordLength, NULL);
446 if (Result == TcgResultSuccess) {
447 Status = EFI_SUCCESS;
448 }
449 }
450
451 if (mSendBlockSID && BlockSidSupport) {
452 Result = OpalBlockSid (&Session, TRUE);
453 if (Result != TcgResultSuccess) {
454 break;
455 }
456 }
457
458 if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
459 if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {
460 Status = NvmeControllerExit (&mNvmeContext);
461 }
462 }
463
464 done:
465 if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
466 ASSERT (RpBase != 0);
467 PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0);
468 RpBase = SaveRestoreRootportConfSpace (
469 OpalDev,
470 FALSE, // restore
471 StorePcieConfDataList
472 );
473 PciWrite8 (RpBase + NVME_PCIE_PCICMD, SataCmdSt);
474 } else {
475 PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), SataCmdSt);
476 }
477
478 if (EFI_ERROR (Status)) {
479 break;
480 }
481 }
482
483 return Status;
484 }
485
486
487 /**
488 Main entry point for an SMM handler dispatch or communicate-based callback.
489
490 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
491 @param[in] Context Points to an optional handler context which was specified when the
492 handler was registered.
493 @param[in,out] CommBuffer A pointer to a collection of Data in memory that will
494 be conveyed from a non-SMM environment into an SMM environment.
495 @param[in,out] CommBufferSize The Size of the CommBuffer.
496
497 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
498 should still be called.
499 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
500 still be called.
501 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
502 be called.
503 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
504 **/
505 EFI_STATUS
506 EFIAPI
507 S3SleepEntryCallBack (
508 IN EFI_HANDLE DispatchHandle,
509 IN CONST VOID *Context OPTIONAL,
510 IN OUT VOID *CommBuffer OPTIONAL,
511 IN OUT UINTN *CommBufferSize OPTIONAL
512 )
513 {
514 UINTN Bus;
515 UINTN Device;
516 UINTN Function;
517 UINTN Index;
518 EFI_STATUS Status;
519 LIST_ENTRY *Entry;
520 UINTN Offset;
521 UINT64 Address;
522 S3_BOOT_SCRIPT_LIB_WIDTH Width;
523 UINT32 Data;
524 OPAL_DISK_AND_PASSWORD_INFO *PciDev;
525 OPAL_HC_PCI_REGISTER_SAVE *HcRegisterSaveListPtr;
526 UINTN Count;
527 OPAL_SMM_DEVICE *SmmDev;
528
529 Data = 0;
530 Status = EFI_SUCCESS;
531
532 mOpalDeviceList = OpalSupportGetOpalDeviceList();
533
534 for (Entry = mOpalDeviceList->ForwardLink; Entry != mOpalDeviceList; Entry = Entry->ForwardLink) {
535 PciDev = BASE_CR (Entry, OPAL_DISK_AND_PASSWORD_INFO, Link);
536
537 SmmDev = AllocateZeroPool (sizeof (OPAL_SMM_DEVICE));
538 if (SmmDev == NULL) {
539 return EFI_OUT_OF_RESOURCES;
540 }
541 SmmDev->Signature = OPAL_SMM_DEVICE_SIGNATURE;
542
543 ExtractDeviceInfoFromDevicePath(&PciDev->OpalDevicePath, SmmDev);
544
545 SmmDev->PasswordLength = PciDev->PasswordLength;
546 CopyMem(&(SmmDev->Password), PciDev->Password, OPAL_PASSWORD_MAX_LENGTH);
547
548 SmmDev->Sscp.ReceiveData = SecurityReceiveData;
549 SmmDev->Sscp.SendData = SecuritySendData;
550
551 InsertHeadList (&mSmmDeviceList, &SmmDev->Link);
552
553 if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
554 continue;
555 }
556
557 //
558 // Save register Data for S3. Sata controller only.
559 //
560 Bus = SmmDev->BusNum;
561 Device = SmmDev->DevNum;
562 Function = SmmDev->FuncNum;
563
564 ASSERT (SmmDev->DeviceType == OPAL_DEVICE_TYPE_SATA);
565 HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *) mSataHcRegisterSaveTemplate;
566 Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof (OPAL_HC_PCI_REGISTER_SAVE);
567
568 for (Index = 0; Index < Count; Index += 1) {
569 Offset = HcRegisterSaveListPtr[Index].Address;
570 Width = HcRegisterSaveListPtr[Index].Width;
571
572 switch (Width) {
573 case S3BootScriptWidthUint8:
574 Data = (UINT32)PciRead8 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
575 break;
576 case S3BootScriptWidthUint16:
577 Data = (UINT32)PciRead16 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
578 break;
579 case S3BootScriptWidthUint32:
580 Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));
581 break;
582 default:
583 ASSERT (FALSE);
584 break;
585 }
586
587 Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function, Offset);
588 Status = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);
589 if (EFI_ERROR (Status)) {
590 return Status;
591 }
592 }
593 }
594
595 if (!IsListEmpty (mOpalDeviceList)) {
596 Status = S3BootScriptSaveIoWrite (S3BootScriptWidthUint8, 0xB2, 1, &mSwSmiValue);
597 ASSERT_EFI_ERROR (Status);
598 }
599
600 return Status;
601 }
602
603 /**
604 OpalPassword Notification for SMM EndOfDxe protocol.
605
606 @param[in] Protocol Points to the protocol's unique identifier.
607 @param[in] Interface Points to the interface instance.
608 @param[in] Handle The handle on which the interface was installed.
609
610 @retval EFI_SUCCESS Notification runs successfully.
611 **/
612 EFI_STATUS
613 EFIAPI
614 OpalPasswordEndOfDxeNotification (
615 IN CONST EFI_GUID *Protocol,
616 IN VOID *Interface,
617 IN EFI_HANDLE Handle
618 )
619 {
620 UINTN NumberOfDescriptors;
621 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap;
622 EFI_STATUS Status;
623
624 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap);
625 if (EFI_ERROR (Status)) {
626 return Status;
627 }
628
629 mGcdMemSpace = AllocateCopyPool (NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR), MemSpaceMap);
630 if (EFI_ERROR (Status)) {
631 gBS->FreePool (MemSpaceMap);
632 return Status;
633 }
634
635 mNumberOfDescriptors = NumberOfDescriptors;
636 gBS->FreePool (MemSpaceMap);
637
638 return EFI_SUCCESS;
639 }
640
641 /**
642 Main entry for this driver.
643
644 @param ImageHandle Image handle this driver.
645 @param SystemTable Pointer to SystemTable.
646
647 @retval EFI_SUCESS This function always complete successfully.
648
649 **/
650 EFI_STATUS
651 EFIAPI
652 OpalPasswordSmmInit (
653 IN EFI_HANDLE ImageHandle,
654 IN EFI_SYSTEM_TABLE *SystemTable
655 )
656 {
657 EFI_STATUS Status;
658 EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
659 EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;
660 EFI_HANDLE SwHandle;
661 EFI_SMM_SW_REGISTER_CONTEXT Context;
662 EFI_HANDLE S3SleepEntryHandle;
663 EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;
664 EFI_SMM_VARIABLE_PROTOCOL *SmmVariable;
665 OPAL_EXTRA_INFO_VAR OpalExtraInfo;
666 UINTN DataSize;
667 EFI_EVENT EndOfDxeEvent;
668 EFI_PHYSICAL_ADDRESS Address;
669
670 mBuffer = NULL;
671 SwHandle = NULL;
672 S3SleepEntryHandle = NULL;
673 ZeroMem (&mNvmeContext, sizeof (NVME_CONTEXT));
674
675 Status = gSmst->SmmLocateProtocol (
676 &gEfiSmmSwDispatch2ProtocolGuid,
677 NULL,
678 (VOID **)&SwDispatch
679 );
680 ASSERT_EFI_ERROR (Status);
681 if (EFI_ERROR (Status)) {
682 DEBUG((DEBUG_ERROR, " SmmLocateProtocol gEfiSmmSwDispatch2ProtocolGuid fail, Status: %r\n", Status));
683 return Status;
684 }
685
686 Status = gSmst->SmmLocateProtocol (
687 &gEfiSmmSxDispatch2ProtocolGuid,
688 NULL,
689 (VOID **)&SxDispatch
690 );
691 ASSERT_EFI_ERROR (Status);
692 if (EFI_ERROR (Status)) {
693 DEBUG((DEBUG_ERROR, " SmmLocateProtocol gEfiSmmSxDispatch2ProtocolGuid fail, Status: %r\n", Status));
694 return Status;
695 }
696
697 //
698 // Preallocate a 512 bytes Buffer to perform trusted I/O.
699 // Assume this is big enough for unlock commands
700 // It's because DMA can not access smmram stack at the cmd execution.
701 //
702 Address = 0xFFFFFFFF;
703 Status = gBS->AllocatePages (
704 AllocateMaxAddress,
705 EfiACPIMemoryNVS,
706 EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES),
707 &Address
708 );
709 if (EFI_ERROR (Status)) {
710 DEBUG((DEBUG_ERROR, " AllocatePages for SATA DAM fail, Status: %r\n", Status));
711 return EFI_OUT_OF_RESOURCES;
712 }
713
714 mBuffer = (VOID *)(UINTN)Address;
715 ZeroMem ((VOID *)(UINTN)mBuffer, SMM_SIZE_ALLOC_BYTES);
716
717 //
718 // Preallocate resource for AHCI transfer descriptor.
719 //
720 Status = AhciAllocateResource ();
721 if (EFI_ERROR (Status)) {
722 DEBUG((DEBUG_ERROR, " AhciAllocateResource fail, Status: %r\n", Status));
723 Status = EFI_OUT_OF_RESOURCES;
724 goto EXIT;
725 }
726
727 //
728 // Preallocate resource for NVMe configuration space.
729 //
730 Status = NvmeAllocateResource (ImageHandle, &mNvmeContext);
731 if (EFI_ERROR (Status)) {
732 DEBUG((DEBUG_ERROR, " NvmeAllocateResource fail, Status: %r\n", Status));
733 Status = EFI_OUT_OF_RESOURCES;
734 goto EXIT;
735 }
736
737 //
738 // Register a S3 entry callback function to store ATA host controller context to boot script.
739 // These boot scripts would be invoked at S3 path to recovery ATA host controller h/w context
740 // for executing HDD unlock cmd.
741 //
742 EntryRegisterContext.Type = SxS3;
743 EntryRegisterContext.Phase = SxEntry;
744 Status = SxDispatch->Register (
745 SxDispatch,
746 S3SleepEntryCallBack,
747 &EntryRegisterContext,
748 &S3SleepEntryHandle
749 );
750 ASSERT_EFI_ERROR (Status);
751 if (EFI_ERROR (Status)) {
752 goto EXIT;
753 }
754
755 //
756 // Register Opal password smm unlock handler
757 //
758 Context.SwSmiInputValue = (UINTN) -1;
759 Status = SwDispatch->Register (
760 SwDispatch,
761 SmmUnlockOpalPassword,
762 &Context,
763 &SwHandle
764 );
765 ASSERT_EFI_ERROR (Status);
766 if (EFI_ERROR (Status)) {
767 DEBUG((DEBUG_ERROR, " SwDispatch->Register fail, Status: %r\n", Status));
768 goto EXIT;
769 }
770
771 //
772 // trigger smi to unlock hdd if it's locked.
773 //
774 mSwSmiValue = (UINT8) Context.SwSmiInputValue;
775
776 //
777 // Create event to record GCD descriptors at end of dxe for judging AHCI/NVMe PCI Bar
778 // is in MMIO space to avoid attack.
779 //
780 Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, OpalPasswordEndOfDxeNotification, &EndOfDxeEvent);
781 if (EFI_ERROR (Status)) {
782 DEBUG((DEBUG_ERROR, "OpalPasswordSmm: Register SmmEndOfDxe fail, Status: %r\n", Status));
783 goto EXIT;
784 }
785 Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&SmmVariable);
786 if (!EFI_ERROR (Status)) {
787 DataSize = sizeof (OPAL_EXTRA_INFO_VAR);
788 Status = SmmVariable->SmmGetVariable (
789 OPAL_EXTRA_INFO_VAR_NAME,
790 &gOpalExtraInfoVariableGuid,
791 NULL,
792 &DataSize,
793 &OpalExtraInfo
794 );
795 if (!EFI_ERROR (Status)) {
796 mSendBlockSID = OpalExtraInfo.EnableBlockSid;
797 }
798 }
799
800 return EFI_SUCCESS;
801
802 EXIT:
803 if (S3SleepEntryHandle != NULL) {
804 SxDispatch->UnRegister (SxDispatch, S3SleepEntryHandle);
805 }
806
807 AhciFreeResource ();
808
809 NvmeFreeResource (&mNvmeContext);
810
811 if (mBuffer != NULL) {
812 gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN) mBuffer, EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES));
813 }
814
815 return Status;
816 }
817
818 /**
819 Provide Io action support.
820
821 @param[in] SmmDev the opal device need to perform trust io.
822 @param[in] IoType OPAL_IO_TYPE indicating whether to perform a Trusted Send or Trusted Receive.
823 @param[in] SecurityProtocol Security Protocol
824 @param[in] SpSpecific Security Protocol Specific
825 @param[in] TransferLength Transfer Length of Buffer (in bytes) - always a multiple of 512
826 @param[in] Buffer Address of Data to transfer
827
828 @retval TcgResultSuccess Perform the io action success.
829 @retval TcgResultFailure Perform the io action failed.
830
831 **/
832 EFI_STATUS
833 PerformTrustedIo (
834 OPAL_SMM_DEVICE *SmmDev,
835 OPAL_IO_TYPE IoType,
836 UINT8 SecurityProtocol,
837 UINT16 SpSpecific,
838 UINTN TransferLength,
839 VOID *Buffer
840 )
841 {
842 EFI_STATUS Status;
843 UINTN BufferSizeBlocks;
844 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
845
846 Status = EFI_DEVICE_ERROR;
847 if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_SATA) {
848 BufferSizeBlocks = TransferLength / 512;
849
850 ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );
851 AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ? ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;
852 AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;
853 AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );
854 AtaCommandBlock.AtaFeatures = SecurityProtocol;
855 AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );
856 AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );
857 AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;
858
859
860 ZeroMem( mBuffer, HDD_PAYLOAD );
861 ASSERT( TransferLength <= HDD_PAYLOAD );
862
863 if (IoType == OpalSend) {
864 CopyMem( mBuffer, Buffer, TransferLength );
865 }
866
867 Status = AhciPioTransfer(
868 &mAhciRegisters,
869 (UINT8) SmmDev->SataPort,
870 (UINT8) SmmDev->SataPortMultiplierPort,
871 NULL,
872 0,
873 ( IoType == OpalSend ) ? FALSE : TRUE, // i/o direction
874 &AtaCommandBlock,
875 NULL,
876 mBuffer,
877 (UINT32)TransferLength,
878 ATA_TIMEOUT
879 );
880
881 if (IoType == OpalRecv) {
882 CopyMem( Buffer, mBuffer, TransferLength );
883 }
884 } else if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {
885 Status = NvmeSecuritySendReceive (
886 &mNvmeContext,
887 IoType == OpalSend,
888 SecurityProtocol,
889 SwapBytes16(SpSpecific),
890 TransferLength,
891 Buffer
892 );
893 } else {
894 DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n", SmmDev->DeviceType));
895 }
896
897 return Status;
898 }
899
900 /**
901 Send a security protocol command to a device that receives data and/or the result
902 of one or more commands sent by SendData.
903
904 The ReceiveData function sends a security protocol command to the given MediaId.
905 The security protocol command sent is defined by SecurityProtocolId and contains
906 the security protocol specific data SecurityProtocolSpecificData. The function
907 returns the data from the security protocol command in PayloadBuffer.
908
909 For devices supporting the SCSI command set, the security protocol command is sent
910 using the SECURITY PROTOCOL IN command defined in SPC-4.
911
912 For devices supporting the ATA command set, the security protocol command is sent
913 using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
914 is non-zero.
915
916 If the PayloadBufferSize is zero, the security protocol command is sent using the
917 Trusted Non-Data command defined in ATA8-ACS.
918
919 If PayloadBufferSize is too small to store the available data from the security
920 protocol command, the function shall copy PayloadBufferSize bytes into the
921 PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
922
923 If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
924 the function shall return EFI_INVALID_PARAMETER.
925
926 If the given MediaId does not support security protocol commands, the function shall
927 return EFI_UNSUPPORTED. If there is no media in the device, the function returns
928 EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
929 the function returns EFI_MEDIA_CHANGED.
930
931 If the security protocol fails to complete within the Timeout period, the function
932 shall return EFI_TIMEOUT.
933
934 If the security protocol command completes without an error, the function shall
935 return EFI_SUCCESS. If the security protocol command completes with an error, the
936 function shall return EFI_DEVICE_ERROR.
937
938 @param This Indicates a pointer to the calling context.
939 @param MediaId ID of the medium to receive data from.
940 @param Timeout The timeout, in 100ns units, to use for the execution
941 of the security protocol command. A Timeout value of 0
942 means that this function will wait indefinitely for the
943 security protocol command to execute. If Timeout is greater
944 than zero, then this function will return EFI_TIMEOUT
945 if the time required to execute the receive data command
946 is greater than Timeout.
947 @param SecurityProtocolId The value of the "Security Protocol" parameter of
948 the security protocol command to be sent.
949 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
950 of the security protocol command to be sent.
951 @param PayloadBufferSize Size in bytes of the payload data buffer.
952 @param PayloadBuffer A pointer to a destination buffer to store the security
953 protocol command specific payload data for the security
954 protocol command. The caller is responsible for having
955 either implicit or explicit ownership of the buffer.
956 @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
957 data written to the payload data buffer.
958
959 @retval EFI_SUCCESS The security protocol command completed successfully.
960 @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
961 data from the device. The PayloadBuffer contains the truncated data.
962 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
963 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
964 @retval EFI_NO_MEDIA There is no media in the device.
965 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
966 @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
967 PayloadBufferSize is non-zero.
968 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
969 protocol command to execute.
970
971 **/
972 EFI_STATUS
973 EFIAPI
974 SecurityReceiveData (
975 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
976 IN UINT32 MediaId,
977 IN UINT64 Timeout,
978 IN UINT8 SecurityProtocolId,
979 IN UINT16 SecurityProtocolSpecificData,
980 IN UINTN PayloadBufferSize,
981 OUT VOID *PayloadBuffer,
982 OUT UINTN *PayloadTransferSize
983 )
984 {
985 OPAL_SMM_DEVICE *SmmDev;
986
987 SmmDev = OPAL_SMM_DEVICE_FROM_THIS (This);
988 if (SmmDev == NULL) {
989 return EFI_DEVICE_ERROR;
990 }
991
992 return PerformTrustedIo (
993 SmmDev,
994 OpalRecv,
995 SecurityProtocolId,
996 SecurityProtocolSpecificData,
997 PayloadBufferSize,
998 PayloadBuffer
999 );
1000 }
1001
1002 /**
1003 Send a security protocol command to a device.
1004
1005 The SendData function sends a security protocol command containing the payload
1006 PayloadBuffer to the given MediaId. The security protocol command sent is
1007 defined by SecurityProtocolId and contains the security protocol specific data
1008 SecurityProtocolSpecificData. If the underlying protocol command requires a
1009 specific padding for the command payload, the SendData function shall add padding
1010 bytes to the command payload to satisfy the padding requirements.
1011
1012 For devices supporting the SCSI command set, the security protocol command is sent
1013 using the SECURITY PROTOCOL OUT command defined in SPC-4.
1014
1015 For devices supporting the ATA command set, the security protocol command is sent
1016 using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
1017 is non-zero. If the PayloadBufferSize is zero, the security protocol command is
1018 sent using the Trusted Non-Data command defined in ATA8-ACS.
1019
1020 If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
1021 return EFI_INVALID_PARAMETER.
1022
1023 If the given MediaId does not support security protocol commands, the function
1024 shall return EFI_UNSUPPORTED. If there is no media in the device, the function
1025 returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
1026 device, the function returns EFI_MEDIA_CHANGED.
1027
1028 If the security protocol fails to complete within the Timeout period, the function
1029 shall return EFI_TIMEOUT.
1030
1031 If the security protocol command completes without an error, the function shall return
1032 EFI_SUCCESS. If the security protocol command completes with an error, the function
1033 shall return EFI_DEVICE_ERROR.
1034
1035 @param This Indicates a pointer to the calling context.
1036 @param MediaId ID of the medium to receive data from.
1037 @param Timeout The timeout, in 100ns units, to use for the execution
1038 of the security protocol command. A Timeout value of 0
1039 means that this function will wait indefinitely for the
1040 security protocol command to execute. If Timeout is greater
1041 than zero, then this function will return EFI_TIMEOUT
1042 if the time required to execute the send data command
1043 is greater than Timeout.
1044 @param SecurityProtocolId The value of the "Security Protocol" parameter of
1045 the security protocol command to be sent.
1046 @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
1047 of the security protocol command to be sent.
1048 @param PayloadBufferSize Size in bytes of the payload data buffer.
1049 @param PayloadBuffer A pointer to a destination buffer to store the security
1050 protocol command specific payload data for the security
1051 protocol command.
1052
1053 @retval EFI_SUCCESS The security protocol command completed successfully.
1054 @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
1055 @retval EFI_DEVICE_ERROR The security protocol command completed with an error.
1056 @retval EFI_NO_MEDIA There is no media in the device.
1057 @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
1058 @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
1059 @retval EFI_TIMEOUT A timeout occurred while waiting for the security
1060 protocol command to execute.
1061
1062 **/
1063 EFI_STATUS
1064 EFIAPI
1065 SecuritySendData (
1066 IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
1067 IN UINT32 MediaId,
1068 IN UINT64 Timeout,
1069 IN UINT8 SecurityProtocolId,
1070 IN UINT16 SecurityProtocolSpecificData,
1071 IN UINTN PayloadBufferSize,
1072 IN VOID *PayloadBuffer
1073 )
1074 {
1075 OPAL_SMM_DEVICE *SmmDev;
1076
1077 SmmDev = OPAL_SMM_DEVICE_FROM_THIS (This);
1078 if (SmmDev == NULL) {
1079 return EFI_DEVICE_ERROR;
1080 }
1081
1082 return PerformTrustedIo (
1083 SmmDev,
1084 OpalSend,
1085 SecurityProtocolId,
1086 SecurityProtocolSpecificData,
1087 PayloadBufferSize,
1088 PayloadBuffer
1089 );
1090
1091 }
1092