2 HDD password driver which is used to support HDD security feature.
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) Microsoft Corporation.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "HddPasswordDxe.h"
13 EFI_GUID mHddPasswordVendorGuid
= HDD_PASSWORD_CONFIG_GUID
;
14 CHAR16 mHddPasswordVendorStorageName
[] = L
"HDD_PASSWORD_CONFIG";
15 LIST_ENTRY mHddPasswordConfigFormList
;
16 UINT32 mNumberOfHddDevices
= 0;
18 EFI_GUID mHddPasswordDeviceInfoGuid
= HDD_PASSWORD_DEVICE_INFO_GUID
;
19 BOOLEAN mHddPasswordEndOfDxe
= FALSE
;
20 HDD_PASSWORD_REQUEST_VARIABLE
*mHddPasswordRequestVariable
= NULL
;
21 UINTN mHddPasswordRequestVariableSize
= 0;
23 HII_VENDOR_DEVICE_PATH mHddPasswordHiiVendorDevicePath
= {
29 (UINT8
)(sizeof (VENDOR_DEVICE_PATH
)),
30 (UINT8
)((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
33 HDD_PASSWORD_CONFIG_GUID
37 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
39 (UINT8
)(END_DEVICE_PATH_LENGTH
),
40 (UINT8
)((END_DEVICE_PATH_LENGTH
) >> 8)
46 Check if the password is full zero.
48 @param[in] Password Points to the data buffer
50 @retval TRUE This password string is full zero.
51 @retval FALSE This password string is not full zero.
61 for (Index
= 0; Index
< HDD_PASSWORD_MAX_LENGTH
; Index
++) {
62 if (Password
[Index
] != 0) {
73 @param[in] ConfigFormEntry Points to HDD_PASSWORD_CONFIG_FORM_ENTRY buffer
74 @param[in,out] TempDevInfo Points to HDD_PASSWORD_DEVICE_INFO buffer
79 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
80 IN OUT HDD_PASSWORD_DEVICE_INFO
*TempDevInfo
83 TempDevInfo
->Device
.Bus
= (UINT8
)ConfigFormEntry
->Bus
;
84 TempDevInfo
->Device
.Device
= (UINT8
)ConfigFormEntry
->Device
;
85 TempDevInfo
->Device
.Function
= (UINT8
)ConfigFormEntry
->Function
;
86 TempDevInfo
->Device
.Port
= ConfigFormEntry
->Port
;
87 TempDevInfo
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
88 CopyMem (TempDevInfo
->Password
, ConfigFormEntry
->Password
, HDD_PASSWORD_MAX_LENGTH
);
89 TempDevInfo
->DevicePathLength
= (UINT32
)GetDevicePathSize (ConfigFormEntry
->DevicePath
);
90 CopyMem (TempDevInfo
->DevicePath
, ConfigFormEntry
->DevicePath
, TempDevInfo
->DevicePathLength
);
94 Build HDD password device info and save them to LockBox.
98 BuildHddPasswordDeviceInfo (
104 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
105 HDD_PASSWORD_DEVICE_INFO
*DevInfo
;
106 HDD_PASSWORD_DEVICE_INFO
*TempDevInfo
;
109 BOOLEAN S3InitDevicesExist
;
110 UINTN S3InitDevicesLength
;
111 EFI_DEVICE_PATH_PROTOCOL
*S3InitDevices
;
112 EFI_DEVICE_PATH_PROTOCOL
*S3InitDevicesBak
;
115 // Build HDD password device info and save them to LockBox.
118 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
119 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
122 // 1. Handle device which already set password.
123 // 2. When request to send freeze command, driver also needs to handle device
124 // which support security feature.
126 if ((!PasswordIsFullZero (ConfigFormEntry
->Password
)) ||
127 ((ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
!= 0) &&
128 (ConfigFormEntry
->IfrData
.SecurityStatus
.Enabled
== 0)))
130 DevInfoLength
+= sizeof (HDD_PASSWORD_DEVICE_INFO
) +
131 GetDevicePathSize (ConfigFormEntry
->DevicePath
);
135 if (DevInfoLength
== 0) {
139 S3InitDevicesLength
= sizeof (DummyData
);
140 Status
= RestoreLockBox (
141 &gS3StorageDeviceInitListGuid
,
145 ASSERT ((Status
== EFI_NOT_FOUND
) || (Status
== EFI_BUFFER_TOO_SMALL
));
146 if (Status
== EFI_NOT_FOUND
) {
147 S3InitDevices
= NULL
;
148 S3InitDevicesExist
= FALSE
;
149 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
150 S3InitDevices
= AllocatePool (S3InitDevicesLength
);
151 ASSERT (S3InitDevices
!= NULL
);
153 Status
= RestoreLockBox (
154 &gS3StorageDeviceInitListGuid
,
158 ASSERT_EFI_ERROR (Status
);
159 S3InitDevicesExist
= TRUE
;
164 DevInfo
= AllocateZeroPool (DevInfoLength
);
165 ASSERT (DevInfo
!= NULL
);
167 TempDevInfo
= DevInfo
;
168 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
169 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
171 if ((!PasswordIsFullZero (ConfigFormEntry
->Password
)) ||
172 ((ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
!= 0) &&
173 (ConfigFormEntry
->IfrData
.SecurityStatus
.Enabled
== 0)))
175 SaveDeviceInfo (ConfigFormEntry
, TempDevInfo
);
177 S3InitDevicesBak
= S3InitDevices
;
178 S3InitDevices
= AppendDevicePathInstance (
180 ConfigFormEntry
->DevicePath
182 if (S3InitDevicesBak
!= NULL
) {
183 FreePool (S3InitDevicesBak
);
186 ASSERT (S3InitDevices
!= NULL
);
188 TempDevInfo
= (HDD_PASSWORD_DEVICE_INFO
*)((UINTN
)TempDevInfo
+
189 sizeof (HDD_PASSWORD_DEVICE_INFO
) +
190 TempDevInfo
->DevicePathLength
);
194 Status
= SaveLockBox (
195 &mHddPasswordDeviceInfoGuid
,
199 ASSERT_EFI_ERROR (Status
);
201 Status
= SetLockBoxAttributes (
202 &mHddPasswordDeviceInfoGuid
,
203 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
205 ASSERT_EFI_ERROR (Status
);
207 S3InitDevicesLength
= GetDevicePathSize (S3InitDevices
);
208 if (S3InitDevicesExist
) {
209 Status
= UpdateLockBox (
210 &gS3StorageDeviceInitListGuid
,
215 ASSERT_EFI_ERROR (Status
);
217 Status
= SaveLockBox (
218 &gS3StorageDeviceInitListGuid
,
222 ASSERT_EFI_ERROR (Status
);
224 Status
= SetLockBoxAttributes (
225 &gS3StorageDeviceInitListGuid
,
226 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
228 ASSERT_EFI_ERROR (Status
);
231 ZeroMem (DevInfo
, DevInfoLength
);
233 FreePool (S3InitDevices
);
237 Send freeze lock cmd through Ata Pass Thru Protocol.
239 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
240 @param[in] Port The port number of the ATA device to send the command.
241 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
242 If there is no port multiplier, then specify 0xFFFF.
244 @retval EFI_SUCCESS Successful to send freeze lock cmd.
245 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
246 @retval EFI_OUT_OF_RESOURCES Not enough memory to send freeze lock cmd.
247 @retval EFI_DEVICE_ERROR Can not send freeze lock cmd.
252 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
254 IN UINT16 PortMultiplierPort
258 EFI_ATA_COMMAND_BLOCK Acb
;
259 EFI_ATA_STATUS_BLOCK
*Asb
;
260 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
262 if (AtaPassThru
== NULL
) {
263 return EFI_INVALID_PARAMETER
;
267 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
268 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
269 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
270 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
271 // may not be aligned when allocated on stack for some compilers. Hence, we
272 // use the API AllocateAlignedPages to ensure this structure is properly
275 Asb
= AllocateAlignedPages (
276 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
277 AtaPassThru
->Mode
->IoAlign
280 return EFI_OUT_OF_RESOURCES
;
284 // Prepare for ATA command block.
286 ZeroMem (&Acb
, sizeof (Acb
));
287 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
288 Acb
.AtaCommand
= ATA_SECURITY_FREEZE_LOCK_CMD
;
289 Acb
.AtaDeviceHead
= (UINT8
)(PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
292 // Prepare for ATA pass through packet.
294 ZeroMem (&Packet
, sizeof (Packet
));
295 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA
;
296 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_NO_DATA_TRANSFER
;
299 Packet
.Timeout
= ATA_TIMEOUT
;
301 Status
= AtaPassThru
->PassThru (
308 if (!EFI_ERROR (Status
) &&
309 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
310 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0))
312 Status
= EFI_DEVICE_ERROR
;
315 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
317 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
322 Get attached harddisk identify data through Ata Pass Thru Protocol.
324 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
325 @param[in] Port The port number of the ATA device to send the command.
326 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
327 If there is no port multiplier, then specify 0xFFFF.
328 @param[in] IdentifyData The buffer to store identify data.
330 @retval EFI_SUCCESS Successful to get identify data.
331 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
332 @retval EFI_OUT_OF_RESOURCES Not enough memory to get identify data.
333 @retval EFI_DEVICE_ERROR Can not get identify data.
337 GetHddDeviceIdentifyData (
338 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
340 IN UINT16 PortMultiplierPort
,
341 IN ATA_IDENTIFY_DATA
*IdentifyData
345 EFI_ATA_COMMAND_BLOCK Acb
;
346 EFI_ATA_STATUS_BLOCK
*Asb
;
347 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
349 if ((AtaPassThru
== NULL
) || (IdentifyData
== NULL
)) {
350 return EFI_INVALID_PARAMETER
;
354 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
355 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
356 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
357 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
358 // may not be aligned when allocated on stack for some compilers. Hence, we
359 // use the API AllocateAlignedPages to ensure this structure is properly
362 Asb
= AllocateAlignedPages (
363 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
364 AtaPassThru
->Mode
->IoAlign
367 return EFI_OUT_OF_RESOURCES
;
371 // Prepare for ATA command block.
373 ZeroMem (&Acb
, sizeof (Acb
));
374 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
375 Acb
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
376 Acb
.AtaDeviceHead
= (UINT8
)(BIT7
| BIT6
| BIT5
| (PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4)));
379 // Prepare for ATA pass through packet.
381 ZeroMem (&Packet
, sizeof (Packet
));
382 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN
;
383 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
| EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT
;
386 Packet
.InDataBuffer
= IdentifyData
;
387 Packet
.InTransferLength
= sizeof (ATA_IDENTIFY_DATA
);
388 Packet
.Timeout
= ATA_TIMEOUT
;
390 Status
= AtaPassThru
->PassThru (
398 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
404 Parse security status according to identify data.
406 @param[in] IdentifyData The buffer to store identify data.
407 @param[in, out] IfrData IFR data to hold security status.
411 GetHddPasswordSecurityStatus (
412 IN ATA_IDENTIFY_DATA
*IdentifyData
,
413 IN OUT HDD_PASSWORD_CONFIG
*IfrData
416 IfrData
->SecurityStatus
.Supported
= (IdentifyData
->command_set_supported_82
& BIT1
) ? 1 : 0;
417 IfrData
->SecurityStatus
.Enabled
= (IdentifyData
->security_status
& BIT1
) ? 1 : 0;
418 IfrData
->SecurityStatus
.Locked
= (IdentifyData
->security_status
& BIT2
) ? 1 : 0;
419 IfrData
->SecurityStatus
.Frozen
= (IdentifyData
->security_status
& BIT3
) ? 1 : 0;
420 IfrData
->SecurityStatus
.UserPasswordStatus
= IfrData
->SecurityStatus
.Enabled
;
421 IfrData
->SecurityStatus
.MasterPasswordStatus
= IfrData
->SecurityStatus
.Supported
;
423 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Supported = %x\n", IfrData
->SecurityStatus
.Supported
));
424 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Enabled = %x\n", IfrData
->SecurityStatus
.Enabled
));
425 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Locked = %x\n", IfrData
->SecurityStatus
.Locked
));
426 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Frozen = %x\n", IfrData
->SecurityStatus
.Frozen
));
427 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.UserPasswordStatus = %x\n", IfrData
->SecurityStatus
.UserPasswordStatus
));
428 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.MasterPasswordStatus = %x\n", IfrData
->SecurityStatus
.MasterPasswordStatus
));
432 Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
434 This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
436 @param Event Event whose notification function is being invoked.
437 @param Context Pointer to the notification function's context.
442 HddPasswordEndOfDxeEventNotify (
448 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
450 ATA_IDENTIFY_DATA IdentifyData
;
452 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
454 mHddPasswordEndOfDxe
= TRUE
;
456 if (mHddPasswordRequestVariable
!= NULL
) {
458 // Free the HDD password request variable buffer here
459 // as the HDD password requests should have been processed.
461 FreePool (mHddPasswordRequestVariable
);
462 mHddPasswordRequestVariable
= NULL
;
463 mHddPasswordRequestVariableSize
= 0;
467 // If no any device, return directly.
469 if (IsListEmpty (&mHddPasswordConfigFormList
)) {
470 gBS
->CloseEvent (Event
);
474 BuildHddPasswordDeviceInfo ();
477 // Zero passsword and freeze lock device.
479 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
480 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
482 ZeroMem (ConfigFormEntry
->Password
, HDD_PASSWORD_MAX_LENGTH
);
485 // Check whether need send freeze lock command.
486 // Below device will be froze:
487 // 1. Device not enable password.
488 // 2. Device enable password and unlocked.
490 if ((ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
!= 0) &&
491 (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
== 0) &&
492 (ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
== 0))
494 Status
= FreezeLockDevice (ConfigFormEntry
->AtaPassThru
, ConfigFormEntry
->Port
, ConfigFormEntry
->PortMultiplierPort
);
495 DEBUG ((DEBUG_INFO
, "FreezeLockDevice return %r!\n", Status
));
496 Status
= GetHddDeviceIdentifyData (
497 ConfigFormEntry
->AtaPassThru
,
498 ConfigFormEntry
->Port
,
499 ConfigFormEntry
->PortMultiplierPort
,
502 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
506 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
508 gBS
->CloseEvent (Event
);
514 @param[in, out] SaltValue Points to the salt buffer, 32 bytes
519 IN OUT UINT8
*SaltValue
522 RandomSeed (NULL
, 0);
523 RandomBytes (SaltValue
, PASSWORD_SALT_SIZE
);
527 Hash the data to get credential.
529 @param[in] Buffer Points to the data buffer
530 @param[in] BufferSize Buffer size
531 @param[in] SaltValue Points to the salt buffer, 32 bytes
532 @param[out] Credential Points to the hashed result
534 @retval TRUE Hash the data successfully.
535 @retval FALSE Failed to hash the data.
543 OUT UINT8
*Credential
555 HashSize
= Sha256GetContextSize ();
556 Hash
= AllocateZeroPool (HashSize
);
557 ASSERT (Hash
!= NULL
);
562 Status
= Sha256Init (Hash
);
567 HashData
= AllocateZeroPool (PASSWORD_SALT_SIZE
+ BufferSize
);
568 ASSERT (HashData
!= NULL
);
569 if (HashData
== NULL
) {
573 CopyMem (HashData
, SaltValue
, PASSWORD_SALT_SIZE
);
574 CopyMem ((UINT8
*)HashData
+ PASSWORD_SALT_SIZE
, Buffer
, BufferSize
);
576 Status
= Sha256Update (Hash
, HashData
, PASSWORD_SALT_SIZE
+ BufferSize
);
581 Status
= Sha256Final (Hash
, Credential
);
588 if (HashData
!= NULL
) {
589 ZeroMem (HashData
, PASSWORD_SALT_SIZE
+ BufferSize
);
597 Save HDD password variable that will be used to validate HDD password
598 when the device is at frozen state.
600 @param[in] ConfigFormEntry The HDD Password configuration form entry.
601 @param[in] Password The hdd password of attached ATA device.
605 SaveHddPasswordVariable (
606 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
611 HDD_PASSWORD_VARIABLE
*TempVariable
;
612 UINTN TempVariableSize
;
613 HDD_PASSWORD_VARIABLE
*NextNode
;
614 HDD_PASSWORD_VARIABLE
*Variable
;
616 HDD_PASSWORD_VARIABLE
*NewVariable
;
617 UINTN NewVariableSize
;
620 UINT8 HashData
[SHA256_DIGEST_SIZE
];
621 UINT8 SaltData
[PASSWORD_SALT_SIZE
];
623 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
626 if (!PasswordIsFullZero (Password
)) {
628 // It is Set/Update HDD Password.
630 ZeroMem (HashData
, sizeof (HashData
));
631 ZeroMem (SaltData
, sizeof (SaltData
));
633 HashOk
= GenerateCredential ((UINT8
*)Password
, HDD_PASSWORD_MAX_LENGTH
, SaltData
, HashData
);
635 DEBUG ((DEBUG_INFO
, "GenerateCredential failed\n"));
640 // It is Disable HDD Password.
641 // Go to delete the variable node for the HDD password device.
651 Status
= GetVariable2 (
652 HDD_PASSWORD_VARIABLE_NAME
,
653 &mHddPasswordVendorGuid
,
658 if (!EFI_ERROR (Status
) && (Variable
!= NULL
)) {
659 TempVariable
= Variable
;
660 TempVariableSize
= VariableSize
;
661 while (TempVariableSize
>= sizeof (HDD_PASSWORD_VARIABLE
)) {
662 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
663 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
664 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
665 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
666 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
))
669 // Found the node for the HDD password device.
672 NextNode
= TempVariable
+ 1;
673 CopyMem (TempVariable
, NextNode
, (UINTN
)Variable
+ VariableSize
- (UINTN
)NextNode
);
674 NewVariable
= Variable
;
675 NewVariableSize
= VariableSize
- sizeof (HDD_PASSWORD_VARIABLE
);
679 TempVariableSize
-= sizeof (HDD_PASSWORD_VARIABLE
);
683 if (NewVariable
== NULL
) {
684 DEBUG ((DEBUG_INFO
, "The variable node for the HDD password device is not found\n"));
687 DEBUG ((DEBUG_INFO
, "HddPassword variable get failed (%r)\n", Status
));
690 if (!EFI_ERROR (Status
) && (Variable
!= NULL
)) {
691 TempVariable
= Variable
;
692 TempVariableSize
= VariableSize
;
693 while (TempVariableSize
>= sizeof (HDD_PASSWORD_VARIABLE
)) {
694 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
695 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
696 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
697 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
698 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
))
701 // Found the node for the HDD password device.
704 CopyMem (TempVariable
->PasswordHash
, HashData
, sizeof (HashData
));
705 CopyMem (TempVariable
->PasswordSalt
, SaltData
, sizeof (SaltData
));
706 NewVariable
= Variable
;
707 NewVariableSize
= VariableSize
;
711 TempVariableSize
-= sizeof (HDD_PASSWORD_VARIABLE
);
715 if (NewVariable
== NULL
) {
717 // The node for the HDD password device is not found.
718 // Create node for the HDD password device.
720 NewVariableSize
= VariableSize
+ sizeof (HDD_PASSWORD_VARIABLE
);
721 NewVariable
= AllocateZeroPool (NewVariableSize
);
722 ASSERT (NewVariable
!= NULL
);
723 CopyMem (NewVariable
, Variable
, VariableSize
);
724 TempVariable
= (HDD_PASSWORD_VARIABLE
*)((UINTN
)NewVariable
+ VariableSize
);
725 TempVariable
->Device
.Bus
= (UINT8
)ConfigFormEntry
->Bus
;
726 TempVariable
->Device
.Device
= (UINT8
)ConfigFormEntry
->Device
;
727 TempVariable
->Device
.Function
= (UINT8
)ConfigFormEntry
->Function
;
728 TempVariable
->Device
.Port
= ConfigFormEntry
->Port
;
729 TempVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
730 CopyMem (TempVariable
->PasswordHash
, HashData
, sizeof (HashData
));
731 CopyMem (TempVariable
->PasswordSalt
, SaltData
, sizeof (SaltData
));
734 NewVariableSize
= sizeof (HDD_PASSWORD_VARIABLE
);
735 NewVariable
= AllocateZeroPool (NewVariableSize
);
736 ASSERT (NewVariable
!= NULL
);
737 NewVariable
->Device
.Bus
= (UINT8
)ConfigFormEntry
->Bus
;
738 NewVariable
->Device
.Device
= (UINT8
)ConfigFormEntry
->Device
;
739 NewVariable
->Device
.Function
= (UINT8
)ConfigFormEntry
->Function
;
740 NewVariable
->Device
.Port
= ConfigFormEntry
->Port
;
741 NewVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
742 CopyMem (NewVariable
->PasswordHash
, HashData
, sizeof (HashData
));
743 CopyMem (NewVariable
->PasswordSalt
, SaltData
, sizeof (SaltData
));
747 if (NewVariable
!= NULL
) {
748 Status
= gRT
->SetVariable (
749 HDD_PASSWORD_VARIABLE_NAME
,
750 &mHddPasswordVendorGuid
,
751 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
755 if (EFI_ERROR (Status
)) {
756 DEBUG ((DEBUG_INFO
, "HddPassword variable set failed (%r)\n", Status
));
760 if (NewVariable
!= Variable
) {
761 FreePool (NewVariable
);
764 if (Variable
!= NULL
) {
768 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
772 Get saved HDD password variable that will be used to validate HDD password
773 when the device is at frozen state.
775 @param[in] ConfigFormEntry The HDD Password configuration form entry.
776 @param[out] HddPasswordVariable The variable node for the HDD password device.
778 @retval TRUE The variable node for the HDD password device is found and returned.
779 @retval FALSE The variable node for the HDD password device is not found.
783 GetSavedHddPasswordVariable (
784 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
785 OUT HDD_PASSWORD_VARIABLE
*HddPasswordVariable
789 HDD_PASSWORD_VARIABLE
*TempVariable
;
790 HDD_PASSWORD_VARIABLE
*Variable
;
794 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
799 Status
= GetVariable2 (
800 HDD_PASSWORD_VARIABLE_NAME
,
801 &mHddPasswordVendorGuid
,
805 if (EFI_ERROR (Status
) || (Variable
== NULL
)) {
806 DEBUG ((DEBUG_INFO
, "HddPassword variable get failed (%r)\n", Status
));
811 TempVariable
= Variable
;
812 while (VariableSize
>= sizeof (HDD_PASSWORD_VARIABLE
)) {
813 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
814 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
815 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
816 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
817 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
))
820 // Found the node for the HDD password device.
823 CopyMem (HddPasswordVariable
, TempVariable
, sizeof (HDD_PASSWORD_VARIABLE
));
828 VariableSize
-= sizeof (HDD_PASSWORD_VARIABLE
);
835 DEBUG ((DEBUG_INFO
, "The variable node for the HDD password device is not found\n"));
838 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
844 Use saved HDD password variable to validate HDD password
845 when the device is at frozen state.
847 @param[in] ConfigFormEntry The HDD Password configuration form entry.
848 @param[in] Password The hdd password of attached ATA device.
850 @retval EFI_SUCCESS Pass to validate the HDD password.
851 @retval EFI_NOT_FOUND The variable node for the HDD password device is not found.
852 @retval EFI_DEVICE_ERROR Failed to generate credential for the HDD password.
853 @retval EFI_INVALID_PARAMETER Failed to validate the HDD password.
857 ValidateHddPassword (
858 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
863 HDD_PASSWORD_VARIABLE HddPasswordVariable
;
865 UINT8 HashData
[SHA256_DIGEST_SIZE
];
867 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
869 if (!GetSavedHddPasswordVariable (ConfigFormEntry
, &HddPasswordVariable
)) {
870 DEBUG ((DEBUG_INFO
, "GetSavedHddPasswordVariable failed\n"));
871 return EFI_NOT_FOUND
;
874 ZeroMem (HashData
, sizeof (HashData
));
875 HashOk
= GenerateCredential ((UINT8
*)Password
, HDD_PASSWORD_MAX_LENGTH
, HddPasswordVariable
.PasswordSalt
, HashData
);
877 DEBUG ((DEBUG_INFO
, "GenerateCredential failed\n"));
878 return EFI_DEVICE_ERROR
;
881 if (CompareMem (HddPasswordVariable
.PasswordHash
, HashData
, sizeof (HashData
)) != 0) {
882 Status
= EFI_INVALID_PARAMETER
;
884 Status
= EFI_SUCCESS
;
887 DEBUG ((DEBUG_INFO
, "%a() - exit (%r)\n", __FUNCTION__
, Status
));
892 Send unlock hdd password cmd through Ata Pass Thru Protocol.
894 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
895 @param[in] Port The port number of the ATA device to send the command.
896 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
897 If there is no port multiplier, then specify 0xFFFF.
898 @param[in] Identifier The identifier to set user or master password.
899 @param[in] Password The hdd password of attached ATA device.
901 @retval EFI_SUCCESS Successful to send unlock hdd password cmd.
902 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
903 @retval EFI_OUT_OF_RESOURCES Not enough memory to send unlock hdd password cmd.
904 @retval EFI_DEVICE_ERROR Can not send unlock hdd password cmd.
909 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
911 IN UINT16 PortMultiplierPort
,
917 EFI_ATA_COMMAND_BLOCK Acb
;
918 EFI_ATA_STATUS_BLOCK
*Asb
;
919 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
920 UINT8 Buffer
[HDD_PAYLOAD
];
922 if ((AtaPassThru
== NULL
) || (Password
== NULL
)) {
923 return EFI_INVALID_PARAMETER
;
927 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
928 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
929 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
930 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
931 // may not be aligned when allocated on stack for some compilers. Hence, we
932 // use the API AllocateAlignedPages to ensure this structure is properly
935 Asb
= AllocateAlignedPages (
936 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
937 AtaPassThru
->Mode
->IoAlign
940 return EFI_OUT_OF_RESOURCES
;
944 // Prepare for ATA command block.
946 ZeroMem (&Acb
, sizeof (Acb
));
947 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
948 Acb
.AtaCommand
= ATA_SECURITY_UNLOCK_CMD
;
949 Acb
.AtaDeviceHead
= (UINT8
)(PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
952 // Prepare for ATA pass through packet.
954 ZeroMem (&Packet
, sizeof (Packet
));
955 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
;
956 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
960 ((CHAR16
*)Buffer
)[0] = Identifier
& BIT0
;
961 CopyMem (&((CHAR16
*)Buffer
)[1], Password
, HDD_PASSWORD_MAX_LENGTH
);
963 Packet
.OutDataBuffer
= Buffer
;
964 Packet
.OutTransferLength
= sizeof (Buffer
);
965 Packet
.Timeout
= ATA_TIMEOUT
;
967 Status
= AtaPassThru
->PassThru (
974 if (!EFI_ERROR (Status
) &&
975 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
976 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0))
978 Status
= EFI_DEVICE_ERROR
;
981 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
983 ZeroMem (Buffer
, sizeof (Buffer
));
985 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
990 Send disable hdd password cmd through Ata Pass Thru Protocol.
992 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
993 @param[in] Port The port number of the ATA device to send the command.
994 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
995 If there is no port multiplier, then specify 0xFFFF.
996 @param[in] Identifier The identifier to set user or master password.
997 @param[in] Password The hdd password of attached ATA device.
999 @retval EFI_SUCCESS Successful to disable hdd password cmd.
1000 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
1001 @retval EFI_OUT_OF_RESOURCES Not enough memory to disable hdd password cmd.
1002 @retval EFI_DEVICE_ERROR Can not disable hdd password cmd.
1006 DisableHddPassword (
1007 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1009 IN UINT16 PortMultiplierPort
,
1010 IN CHAR8 Identifier
,
1015 EFI_ATA_COMMAND_BLOCK Acb
;
1016 EFI_ATA_STATUS_BLOCK
*Asb
;
1017 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
1018 UINT8 Buffer
[HDD_PAYLOAD
];
1020 if ((AtaPassThru
== NULL
) || (Password
== NULL
)) {
1021 return EFI_INVALID_PARAMETER
;
1025 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
1026 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
1027 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
1028 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
1029 // may not be aligned when allocated on stack for some compilers. Hence, we
1030 // use the API AllocateAlignedPages to ensure this structure is properly
1033 Asb
= AllocateAlignedPages (
1034 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
1035 AtaPassThru
->Mode
->IoAlign
1038 return EFI_OUT_OF_RESOURCES
;
1042 // Prepare for ATA command block.
1044 ZeroMem (&Acb
, sizeof (Acb
));
1045 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
1046 Acb
.AtaCommand
= ATA_SECURITY_DIS_PASSWORD_CMD
;
1047 Acb
.AtaDeviceHead
= (UINT8
)(PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
1050 // Prepare for ATA pass through packet.
1052 ZeroMem (&Packet
, sizeof (Packet
));
1053 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
;
1054 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
1058 ((CHAR16
*)Buffer
)[0] = Identifier
& BIT0
;
1059 CopyMem (&((CHAR16
*)Buffer
)[1], Password
, HDD_PASSWORD_MAX_LENGTH
);
1061 Packet
.OutDataBuffer
= Buffer
;
1062 Packet
.OutTransferLength
= sizeof (Buffer
);
1063 Packet
.Timeout
= ATA_TIMEOUT
;
1065 Status
= AtaPassThru
->PassThru (
1072 if (!EFI_ERROR (Status
) &&
1073 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
1074 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0))
1076 Status
= EFI_DEVICE_ERROR
;
1079 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
1081 ZeroMem (Buffer
, sizeof (Buffer
));
1083 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
1088 Send set hdd password cmd through Ata Pass Thru Protocol.
1090 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
1091 @param[in] Port The port number of the ATA device to send the command.
1092 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
1093 If there is no port multiplier, then specify 0xFFFF.
1094 @param[in] Identifier The identifier to set user or master password.
1095 @param[in] SecurityLevel The security level to be set to device.
1096 @param[in] MasterPasswordIdentifier The master password identifier to be set to device.
1097 @param[in] Password The hdd password of attached ATA device.
1099 @retval EFI_SUCCESS Successful to set hdd password cmd.
1100 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
1101 @retval EFI_OUT_OF_RESOURCES Not enough memory to set hdd password cmd.
1102 @retval EFI_DEVICE_ERROR Can not set hdd password cmd.
1107 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1109 IN UINT16 PortMultiplierPort
,
1110 IN CHAR8 Identifier
,
1111 IN CHAR8 SecurityLevel
,
1112 IN CHAR16 MasterPasswordIdentifier
,
1117 EFI_ATA_COMMAND_BLOCK Acb
;
1118 EFI_ATA_STATUS_BLOCK
*Asb
;
1119 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
1120 UINT8 Buffer
[HDD_PAYLOAD
];
1122 if ((AtaPassThru
== NULL
) || (Password
== NULL
)) {
1123 return EFI_INVALID_PARAMETER
;
1127 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
1128 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
1129 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
1130 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
1131 // may not be aligned when allocated on stack for some compilers. Hence, we
1132 // use the API AllocateAlignedPages to ensure this structure is properly
1135 Asb
= AllocateAlignedPages (
1136 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
1137 AtaPassThru
->Mode
->IoAlign
1140 return EFI_OUT_OF_RESOURCES
;
1144 // Prepare for ATA command block.
1146 ZeroMem (&Acb
, sizeof (Acb
));
1147 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
1148 Acb
.AtaCommand
= ATA_SECURITY_SET_PASSWORD_CMD
;
1149 Acb
.AtaDeviceHead
= (UINT8
)(PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
1152 // Prepare for ATA pass through packet.
1154 ZeroMem (&Packet
, sizeof (Packet
));
1155 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
;
1156 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
1160 ((CHAR16
*)Buffer
)[0] = (Identifier
| (UINT16
)(SecurityLevel
<< 8)) & (BIT0
| BIT8
);
1161 CopyMem (&((CHAR16
*)Buffer
)[1], Password
, HDD_PASSWORD_MAX_LENGTH
);
1162 if ((Identifier
& BIT0
) != 0) {
1163 ((CHAR16
*)Buffer
)[17] = MasterPasswordIdentifier
;
1166 Packet
.OutDataBuffer
= Buffer
;
1167 Packet
.OutTransferLength
= sizeof (Buffer
);
1168 Packet
.Timeout
= ATA_TIMEOUT
;
1170 Status
= AtaPassThru
->PassThru (
1177 if (!EFI_ERROR (Status
) &&
1178 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
1179 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0))
1181 Status
= EFI_DEVICE_ERROR
;
1184 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
1186 ZeroMem (Buffer
, sizeof (Buffer
));
1188 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
1193 Get attached harddisk model number from identify data buffer.
1195 @param[in] IdentifyData Pointer to identify data buffer.
1196 @param[in, out] String The buffer to store harddisk model number.
1200 GetHddDeviceModelNumber (
1201 IN ATA_IDENTIFY_DATA
*IdentifyData
,
1202 IN OUT CHAR16
*String
1208 // Swap the byte order in the original module name.
1209 // From Ata spec, the maximum length is 40 bytes.
1211 for (Index
= 0; Index
< 40; Index
+= 2) {
1212 String
[Index
] = IdentifyData
->ModelName
[Index
+ 1];
1213 String
[Index
+ 1] = IdentifyData
->ModelName
[Index
];
1217 // Chap it off after 20 characters
1225 Get password input from the popup windows.
1227 @param[in] PopUpString1 Pop up string 1.
1228 @param[in] PopUpString2 Pop up string 2.
1229 @param[in, out] Password The buffer to hold the input password.
1231 @retval EFI_ABORTED It is given up by pressing 'ESC' key.
1232 @retval EFI_SUCCESS Get password input successfully.
1236 PopupHddPasswordInputWindows (
1237 IN CHAR16
*PopUpString1
,
1238 IN CHAR16
*PopUpString2
,
1239 IN OUT CHAR8
*Password
1244 CHAR16 Mask
[HDD_PASSWORD_MAX_LENGTH
+ 1];
1245 CHAR16 Unicode
[HDD_PASSWORD_MAX_LENGTH
+ 1];
1246 CHAR8 Ascii
[HDD_PASSWORD_MAX_LENGTH
+ 1];
1248 ZeroMem (Unicode
, sizeof (Unicode
));
1249 ZeroMem (Ascii
, sizeof (Ascii
));
1250 ZeroMem (Mask
, sizeof (Mask
));
1252 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1256 Mask
[Length
] = L
'_';
1257 if (PopUpString2
== NULL
) {
1259 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1262 L
"---------------------",
1268 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1272 L
"---------------------",
1281 if (Key
.ScanCode
== SCAN_NULL
) {
1282 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1284 // Add the null terminator.
1286 Unicode
[Length
] = 0;
1288 } else if ((Key
.UnicodeChar
== CHAR_NULL
) ||
1289 (Key
.UnicodeChar
== CHAR_TAB
) ||
1290 (Key
.UnicodeChar
== CHAR_LINEFEED
)
1295 if (Key
.UnicodeChar
== CHAR_BACKSPACE
) {
1297 Unicode
[Length
] = 0;
1302 Unicode
[Length
] = Key
.UnicodeChar
;
1303 Mask
[Length
] = L
'*';
1305 if (Length
== HDD_PASSWORD_MAX_LENGTH
) {
1307 // Add the null terminator.
1309 Unicode
[Length
] = 0;
1317 if (Key
.ScanCode
== SCAN_ESC
) {
1318 ZeroMem (Unicode
, sizeof (Unicode
));
1319 ZeroMem (Ascii
, sizeof (Ascii
));
1320 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1325 UnicodeStrToAsciiStrS (Unicode
, Ascii
, sizeof (Ascii
));
1326 CopyMem (Password
, Ascii
, HDD_PASSWORD_MAX_LENGTH
);
1327 ZeroMem (Unicode
, sizeof (Unicode
));
1328 ZeroMem (Ascii
, sizeof (Ascii
));
1330 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1335 Check if disk is locked, show popup window and ask for password if it is.
1337 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1338 @param[in] Port The port number of attached ATA device.
1339 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1340 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1344 HddPasswordRequestPassword (
1345 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1347 IN UINT16 PortMultiplierPort
,
1348 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1352 CHAR16 PopUpString
[100];
1353 ATA_IDENTIFY_DATA IdentifyData
;
1356 CHAR8 Password
[HDD_PASSWORD_MAX_LENGTH
];
1360 DEBUG ((DEBUG_INFO
, "%a()\n", __FUNCTION__
));
1362 UnicodeSPrint (PopUpString
, sizeof (PopUpString
), L
"Unlock: %s", ConfigFormEntry
->HddString
);
1365 // Check the device security status.
1367 if ((ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
) &&
1368 (ConfigFormEntry
->IfrData
.SecurityStatus
.Enabled
))
1371 // Add PcdSkipHddPasswordPrompt to determin whether to skip password prompt.
1372 // Due to board design, device may not power off during system warm boot, which result in
1373 // security status remain unlocked status, hence we add device security status check here.
1375 // If device is in the locked status, device keeps locked and system continues booting.
1376 // If device is in the unlocked status, system is forced shutdown for security concern.
1378 if (PcdGetBool (PcdSkipHddPasswordPrompt
)) {
1379 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1382 gRT
->ResetSystem (EfiResetShutdown
, EFI_SUCCESS
, 0, NULL
);
1387 // As soon as the HDD password is in enabled state, we pop up a window to unlock hdd
1388 // no matter it's really in locked or unlocked state.
1389 // This way forces user to enter password every time to provide best safety.
1392 Status
= PopupHddPasswordInputWindows (PopUpString
, NULL
, Password
);
1393 if (!EFI_ERROR (Status
)) {
1395 // The HDD is in locked state, unlock it by user input.
1397 if (!PasswordIsFullZero (Password
)) {
1398 if (!ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1399 Status
= UnlockHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 0, Password
);
1402 // Use saved HDD password variable to validate HDD password
1403 // when the device is at frozen state.
1405 Status
= ValidateHddPassword (ConfigFormEntry
, Password
);
1408 Status
= EFI_INVALID_PARAMETER
;
1411 if (!EFI_ERROR (Status
)) {
1412 CopyMem (ConfigFormEntry
->Password
, Password
, HDD_PASSWORD_MAX_LENGTH
);
1413 if (!ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1414 SaveHddPasswordVariable (ConfigFormEntry
, Password
);
1417 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1418 Status
= GetHddDeviceIdentifyData (AtaPassThru
, Port
, PortMultiplierPort
, &IdentifyData
);
1419 ASSERT_EFI_ERROR (Status
);
1422 // Check the device security status again.
1424 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
1428 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1430 if (EFI_ERROR (Status
)) {
1432 if (RetryCount
< MAX_HDD_PASSWORD_RETRY_COUNT
) {
1435 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1437 L
"Invalid password.",
1438 L
"Press ENTER to retry",
1441 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1447 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1449 L
"Hdd password retry count is expired. Please shutdown the machine.",
1450 L
"Press ENTER to shutdown",
1453 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1455 gRT
->ResetSystem (EfiResetShutdown
, EFI_SUCCESS
, 0, NULL
);
1459 } else if (Status
== EFI_ABORTED
) {
1460 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1462 // Current device in the lock status and
1463 // User not input password and press ESC,
1464 // keep device in lock status and continue boot.
1468 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1470 L
"Press ENTER to skip the request and continue boot,",
1471 L
"Press ESC to input password again",
1474 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1476 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1477 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1479 // Keep lock and continue boot.
1484 // Let user input password again.
1490 // Current device in the unlock status and
1491 // User not input password and press ESC,
1492 // Shutdown the device.
1496 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1498 L
"Press ENTER to shutdown, Press ESC to input password again",
1501 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1503 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1504 gRT
->ResetSystem (EfiResetShutdown
, EFI_SUCCESS
, 0, NULL
);
1507 // Let user input password again.
1518 Process Set User Pwd HDD password request.
1520 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1521 @param[in] Port The port number of attached ATA device.
1522 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1523 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1527 ProcessHddPasswordRequestSetUserPwd (
1528 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1530 IN UINT16 PortMultiplierPort
,
1531 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1535 CHAR16 PopUpString
[100];
1536 ATA_IDENTIFY_DATA IdentifyData
;
1539 CHAR8 Password
[HDD_PASSWORD_MAX_LENGTH
];
1540 CHAR8 PasswordConfirm
[HDD_PASSWORD_MAX_LENGTH
];
1544 DEBUG ((DEBUG_INFO
, "%a()\n", __FUNCTION__
));
1546 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1547 DEBUG ((DEBUG_INFO
, "%s is frozen, do nothing\n", ConfigFormEntry
->HddString
));
1551 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1552 DEBUG ((DEBUG_INFO
, "%s is locked, do nothing\n", ConfigFormEntry
->HddString
));
1556 UnicodeSPrint (PopUpString
, sizeof (PopUpString
), L
"Set User Pwd: %s", ConfigFormEntry
->HddString
);
1559 // Check the device security status.
1561 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
) {
1563 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please type in your new password", Password
);
1564 if (!EFI_ERROR (Status
)) {
1565 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please confirm your new password", PasswordConfirm
);
1566 if (!EFI_ERROR (Status
)) {
1567 if (CompareMem (Password
, PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
) == 0) {
1568 if (!PasswordIsFullZero (Password
)) {
1569 Status
= SetHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 0, 1, 0, Password
);
1571 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Enabled
) {
1572 Status
= DisableHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 0, ConfigFormEntry
->Password
);
1574 Status
= EFI_INVALID_PARAMETER
;
1578 if (!EFI_ERROR (Status
)) {
1579 CopyMem (ConfigFormEntry
->Password
, Password
, HDD_PASSWORD_MAX_LENGTH
);
1580 SaveHddPasswordVariable (ConfigFormEntry
, Password
);
1581 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1582 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1583 Status
= GetHddDeviceIdentifyData (AtaPassThru
, Port
, PortMultiplierPort
, &IdentifyData
);
1584 ASSERT_EFI_ERROR (Status
);
1587 // Check the device security status again.
1589 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
1594 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1596 L
"Set/Disable User Pwd failed or invalid password.",
1597 L
"Press ENTER to retry",
1600 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1605 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1607 L
"Passwords are not the same.",
1608 L
"Press ENTER to retry",
1611 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1613 Status
= EFI_INVALID_PARAMETER
;
1617 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1618 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1620 if (EFI_ERROR (Status
)) {
1622 if (RetryCount
>= MAX_HDD_PASSWORD_RETRY_COUNT
) {
1625 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1627 L
"Hdd password retry count is expired.",
1628 L
"Press ENTER to skip the request and continue boot",
1631 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1633 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1637 } else if (Status
== EFI_ABORTED
) {
1640 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1642 L
"Press ENTER to skip the request and continue boot,",
1643 L
"Press ESC to input password again",
1646 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1648 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1649 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1653 // Let user input password again.
1663 Process Set Master Pwd HDD password request.
1665 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1666 @param[in] Port The port number of attached ATA device.
1667 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1668 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1672 ProcessHddPasswordRequestSetMasterPwd (
1673 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1675 IN UINT16 PortMultiplierPort
,
1676 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1680 CHAR16 PopUpString
[100];
1683 CHAR8 Password
[HDD_PASSWORD_MAX_LENGTH
];
1684 CHAR8 PasswordConfirm
[HDD_PASSWORD_MAX_LENGTH
];
1688 DEBUG ((DEBUG_INFO
, "%a()\n", __FUNCTION__
));
1690 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1691 DEBUG ((DEBUG_INFO
, "%s is frozen, do nothing\n", ConfigFormEntry
->HddString
));
1695 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1696 DEBUG ((DEBUG_INFO
, "%s is locked, do nothing\n", ConfigFormEntry
->HddString
));
1700 UnicodeSPrint (PopUpString
, sizeof (PopUpString
), L
"Set Master Pwd: %s", ConfigFormEntry
->HddString
);
1703 // Check the device security status.
1705 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
) {
1707 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please type in your new password", Password
);
1708 if (!EFI_ERROR (Status
)) {
1709 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please confirm your new password", PasswordConfirm
);
1710 if (!EFI_ERROR (Status
)) {
1711 if (CompareMem (Password
, PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
) == 0) {
1712 if (!PasswordIsFullZero (Password
)) {
1713 Status
= SetHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 1, 1, 1, Password
);
1715 Status
= EFI_INVALID_PARAMETER
;
1718 if (!EFI_ERROR (Status
)) {
1719 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1720 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1725 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1727 L
"Set Master Pwd failed or invalid password.",
1728 L
"Press ENTER to retry",
1731 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1736 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1738 L
"Passwords are not the same.",
1739 L
"Press ENTER to retry",
1742 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1744 Status
= EFI_INVALID_PARAMETER
;
1748 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1749 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1751 if (EFI_ERROR (Status
)) {
1753 if (RetryCount
>= MAX_HDD_PASSWORD_RETRY_COUNT
) {
1756 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1758 L
"Hdd password retry count is expired.",
1759 L
"Press ENTER to skip the request and continue boot",
1762 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1764 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1768 } else if (Status
== EFI_ABORTED
) {
1771 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1773 L
"Press ENTER to skip the request and continue boot,",
1774 L
"Press ESC to input password again",
1777 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1779 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1780 gST
->ConOut
->ClearScreen (gST
->ConOut
);
1784 // Let user input password again.
1794 Process HDD password request.
1796 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1797 @param[in] Port The port number of attached ATA device.
1798 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1799 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1803 ProcessHddPasswordRequest (
1804 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1806 IN UINT16 PortMultiplierPort
,
1807 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1811 HDD_PASSWORD_REQUEST_VARIABLE
*TempVariable
;
1812 HDD_PASSWORD_REQUEST_VARIABLE
*Variable
;
1815 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
1817 if (mHddPasswordRequestVariable
== NULL
) {
1818 Status
= GetVariable2 (
1819 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1820 &mHddPasswordVendorGuid
,
1824 if (EFI_ERROR (Status
) || (Variable
== NULL
)) {
1828 mHddPasswordRequestVariable
= Variable
;
1829 mHddPasswordRequestVariableSize
= VariableSize
;
1832 // Delete the HDD password request variable.
1834 Status
= gRT
->SetVariable (
1835 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1836 &mHddPasswordVendorGuid
,
1841 ASSERT_EFI_ERROR (Status
);
1843 Variable
= mHddPasswordRequestVariable
;
1844 VariableSize
= mHddPasswordRequestVariableSize
;
1848 // Process the HDD password requests.
1850 TempVariable
= Variable
;
1851 while (VariableSize
>= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
)) {
1852 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
1853 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
1854 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
1855 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
1856 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
))
1859 // Found the node for the HDD password device.
1861 if (TempVariable
->Request
.UserPassword
!= 0) {
1862 ProcessHddPasswordRequestSetUserPwd (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
1865 if (TempVariable
->Request
.MasterPassword
!= 0) {
1866 ProcessHddPasswordRequestSetMasterPwd (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
1872 VariableSize
-= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
1876 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
1880 Get saved HDD password request.
1882 @param[in, out] ConfigFormEntry The HDD Password configuration form entry.
1886 GetSavedHddPasswordRequest (
1887 IN OUT HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1891 HDD_PASSWORD_REQUEST_VARIABLE
*TempVariable
;
1892 HDD_PASSWORD_REQUEST_VARIABLE
*Variable
;
1895 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
1900 Status
= GetVariable2 (
1901 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1902 &mHddPasswordVendorGuid
,
1906 if (EFI_ERROR (Status
) || (Variable
== NULL
)) {
1910 TempVariable
= Variable
;
1911 while (VariableSize
>= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
)) {
1912 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
1913 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
1914 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
1915 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
1916 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
))
1919 // Found the node for the HDD password device.
1920 // Get the HDD password request.
1922 CopyMem (&ConfigFormEntry
->IfrData
.Request
, &TempVariable
->Request
, sizeof (HDD_PASSWORD_REQUEST
));
1925 "HddPasswordRequest got: 0x%x\n",
1926 ConfigFormEntry
->IfrData
.Request
1931 VariableSize
-= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
1935 FreePool (Variable
);
1937 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
1941 Save HDD password request.
1943 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1947 SaveHddPasswordRequest (
1948 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1952 HDD_PASSWORD_REQUEST_VARIABLE
*TempVariable
;
1953 UINTN TempVariableSize
;
1954 HDD_PASSWORD_REQUEST_VARIABLE
*Variable
;
1956 HDD_PASSWORD_REQUEST_VARIABLE
*NewVariable
;
1957 UINTN NewVariableSize
;
1959 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
1963 "HddPasswordRequest to save: 0x%x\n",
1964 ConfigFormEntry
->IfrData
.Request
1970 NewVariableSize
= 0;
1972 Status
= GetVariable2 (
1973 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1974 &mHddPasswordVendorGuid
,
1978 if (!EFI_ERROR (Status
) && (Variable
!= NULL
)) {
1979 TempVariable
= Variable
;
1980 TempVariableSize
= VariableSize
;
1981 while (TempVariableSize
>= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
)) {
1982 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
1983 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
1984 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
1985 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
1986 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
))
1989 // Found the node for the HDD password device.
1990 // Update the HDD password request.
1992 CopyMem (&TempVariable
->Request
, &ConfigFormEntry
->IfrData
.Request
, sizeof (HDD_PASSWORD_REQUEST
));
1993 NewVariable
= Variable
;
1994 NewVariableSize
= VariableSize
;
1998 TempVariableSize
-= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
2002 if (NewVariable
== NULL
) {
2004 // The node for the HDD password device is not found.
2005 // Create node for the HDD password device.
2007 NewVariableSize
= VariableSize
+ sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
2008 NewVariable
= AllocateZeroPool (NewVariableSize
);
2009 ASSERT (NewVariable
!= NULL
);
2010 CopyMem (NewVariable
, Variable
, VariableSize
);
2011 TempVariable
= (HDD_PASSWORD_REQUEST_VARIABLE
*)((UINTN
)NewVariable
+ VariableSize
);
2012 TempVariable
->Device
.Bus
= (UINT8
)ConfigFormEntry
->Bus
;
2013 TempVariable
->Device
.Device
= (UINT8
)ConfigFormEntry
->Device
;
2014 TempVariable
->Device
.Function
= (UINT8
)ConfigFormEntry
->Function
;
2015 TempVariable
->Device
.Port
= ConfigFormEntry
->Port
;
2016 TempVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
2017 CopyMem (&TempVariable
->Request
, &ConfigFormEntry
->IfrData
.Request
, sizeof (HDD_PASSWORD_REQUEST
));
2020 NewVariableSize
= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
2021 NewVariable
= AllocateZeroPool (NewVariableSize
);
2022 ASSERT (NewVariable
!= NULL
);
2023 NewVariable
->Device
.Bus
= (UINT8
)ConfigFormEntry
->Bus
;
2024 NewVariable
->Device
.Device
= (UINT8
)ConfigFormEntry
->Device
;
2025 NewVariable
->Device
.Function
= (UINT8
)ConfigFormEntry
->Function
;
2026 NewVariable
->Device
.Port
= ConfigFormEntry
->Port
;
2027 NewVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
2028 CopyMem (&NewVariable
->Request
, &ConfigFormEntry
->IfrData
.Request
, sizeof (HDD_PASSWORD_REQUEST
));
2031 Status
= gRT
->SetVariable (
2032 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
2033 &mHddPasswordVendorGuid
,
2034 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2038 if (EFI_ERROR (Status
)) {
2039 DEBUG ((DEBUG_INFO
, "HddPasswordRequest variable set failed (%r)\n", Status
));
2042 if (NewVariable
!= Variable
) {
2043 FreePool (NewVariable
);
2046 if (Variable
!= NULL
) {
2047 FreePool (Variable
);
2050 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
2054 Get the HDD Password configuration form entry by the index of the goto opcode activated.
2056 @param[in] Index The 0-based index of the goto opcode activated.
2058 @return The HDD Password configuration form entry found.
2060 HDD_PASSWORD_CONFIG_FORM_ENTRY
*
2061 HddPasswordGetConfigFormEntryByIndex (
2066 UINT32 CurrentIndex
;
2067 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
2070 ConfigFormEntry
= NULL
;
2072 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
2073 if (CurrentIndex
== Index
) {
2074 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
2081 return ConfigFormEntry
;
2085 This function allows the caller to request the current
2086 configuration for one or more named elements. The resulting
2087 string is in <ConfigAltResp> format. Any and all alternative
2088 configuration strings shall also be appended to the end of the
2089 current configuration string. If they are, they must appear
2090 after the current configuration. They must contain the same
2091 routing (GUID, NAME, PATH) as the current configuration string.
2092 They must have an additional description indicating the type of
2093 alternative configuration the string represents,
2094 "ALTCFG=<StringToken>". That <StringToken> (when
2095 converted from Hex UNICODE to binary) is a reference to a
2096 string in the associated string pack.
2098 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2099 @param[in] Request A null-terminated Unicode string in
2100 <ConfigRequest> format. Note that this
2101 includes the routing information as well as
2102 the configurable name / value pairs. It is
2103 invalid for this string to be in
2104 <MultiConfigRequest> format.
2105 @param[out] Progress On return, points to a character in the
2106 Request string. Points to the string's null
2107 terminator if request was successful. Points
2108 to the most recent "&" before the first
2109 failing name / value pair (or the beginning
2110 of the string if the failure is in the first
2111 name / value pair) if the request was not
2113 @param[out] Results A null-terminated Unicode string in
2114 <ConfigAltResp> format which has all values
2115 filled in for the names in the Request string.
2116 String to be allocated by the called function.
2118 @retval EFI_SUCCESS The Results string is filled with the
2119 values corresponding to all requested
2121 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2122 parts of the results that must be
2123 stored awaiting possible future
2125 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2126 for the Request parameter
2127 would result in this type of
2128 error. In this case, the
2129 Progress parameter would be
2131 @retval EFI_NOT_FOUND Routing data doesn't match any
2132 known driver. Progress set to the
2133 first character in the routing header.
2134 Note: There is no requirement that the
2135 driver validate the routing data. It
2136 must skip the <ConfigHdr> in order to
2138 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2139 to most recent & before the
2140 error or the beginning of the
2142 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2143 to the & before the name in
2144 question.Currently not implemented.
2148 HddPasswordFormExtractConfig (
2149 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2150 IN CONST EFI_STRING Request
,
2151 OUT EFI_STRING
*Progress
,
2152 OUT EFI_STRING
*Results
2157 HDD_PASSWORD_CONFIG
*IfrData
;
2158 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2159 EFI_STRING ConfigRequestHdr
;
2160 EFI_STRING ConfigRequest
;
2161 BOOLEAN AllocatedRequest
;
2164 if ((Progress
== NULL
) || (Results
== NULL
)) {
2165 return EFI_INVALID_PARAMETER
;
2168 *Progress
= Request
;
2169 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
)) {
2170 return EFI_NOT_FOUND
;
2173 ConfigRequestHdr
= NULL
;
2174 ConfigRequest
= NULL
;
2175 AllocatedRequest
= FALSE
;
2178 Private
= HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This
);
2179 IfrData
= AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG
));
2180 ASSERT (IfrData
!= NULL
);
2181 if (Private
->Current
!= NULL
) {
2182 CopyMem (IfrData
, &Private
->Current
->IfrData
, sizeof (HDD_PASSWORD_CONFIG
));
2186 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
2188 BufferSize
= sizeof (HDD_PASSWORD_CONFIG
);
2189 ConfigRequest
= Request
;
2190 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2192 // Request has no request element, construct full request string.
2193 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2194 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2196 ConfigRequestHdr
= HiiConstructConfigHdr (&mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
, Private
->DriverHandle
);
2197 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2198 ConfigRequest
= AllocateZeroPool (Size
);
2199 ASSERT (ConfigRequest
!= NULL
);
2200 AllocatedRequest
= TRUE
;
2201 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2202 FreePool (ConfigRequestHdr
);
2205 Status
= gHiiConfigRouting
->BlockToConfig (
2215 // Free the allocated config request string.
2217 if (AllocatedRequest
) {
2218 FreePool (ConfigRequest
);
2219 ConfigRequest
= NULL
;
2223 // Set Progress string to the original request string.
2225 if (Request
== NULL
) {
2227 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2228 *Progress
= Request
+ StrLen (Request
);
2235 This function applies changes in a driver's configuration.
2236 Input is a Configuration, which has the routing data for this
2237 driver followed by name / value configuration pairs. The driver
2238 must apply those pairs to its configurable storage. If the
2239 driver's configuration is stored in a linear block of data
2240 and the driver's name / value pairs are in <BlockConfig>
2241 format, it may use the ConfigToBlock helper function (above) to
2242 simplify the job. Currently not implemented.
2244 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2245 @param[in] Configuration A null-terminated Unicode string in
2246 <ConfigString> format.
2247 @param[out] Progress A pointer to a string filled in with the
2248 offset of the most recent '&' before the
2249 first failing name / value pair (or the
2250 beginn ing of the string if the failure
2251 is in the first name / value pair) or
2252 the terminating NULL if all was
2255 @retval EFI_SUCCESS The results have been distributed or are
2256 awaiting distribution.
2257 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2258 parts of the results that must be
2259 stored awaiting possible future
2261 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2262 Results parameter would result
2263 in this type of error.
2264 @retval EFI_NOT_FOUND Target for the specified routing data
2269 HddPasswordFormRouteConfig (
2270 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2271 IN CONST EFI_STRING Configuration
,
2272 OUT EFI_STRING
*Progress
2275 if ((Configuration
== NULL
) || (Progress
== NULL
)) {
2276 return EFI_INVALID_PARAMETER
;
2280 // Check routing data in <ConfigHdr>.
2281 // Note: if only one Storage is used, then this checking could be skipped.
2283 if (!HiiIsConfigHdrMatch (Configuration
, &mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
)) {
2284 *Progress
= Configuration
;
2285 return EFI_NOT_FOUND
;
2288 *Progress
= Configuration
+ StrLen (Configuration
);
2293 This function is called to provide results data to the driver.
2294 This data consists of a unique key that is used to identify
2295 which data is either being passed back or being asked for.
2297 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2298 @param[in] Action Specifies the type of action taken by the browser.
2299 @param[in] QuestionId A unique value which is sent to the original
2300 exporting driver so that it can identify the type
2301 of data to expect. The format of the data tends to
2302 vary based on the opcode that enerated the callback.
2303 @param[in] Type The type of value for the question.
2304 @param[in] Value A pointer to the data being sent to the original
2306 @param[out] ActionRequest On return, points to the action requested by the
2309 @retval EFI_SUCCESS The callback successfully handled the action.
2310 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2311 variable and its data.
2312 @retval EFI_DEVICE_ERROR The variable could not be saved.
2313 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2314 callback.Currently not implemented.
2315 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
2316 @retval Others Other errors as indicated.
2320 HddPasswordFormCallback (
2321 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2322 IN EFI_BROWSER_ACTION Action
,
2323 IN EFI_QUESTION_ID QuestionId
,
2325 IN EFI_IFR_TYPE_VALUE
*Value
,
2326 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2329 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2330 EFI_STRING_ID DeviceFormTitleToken
;
2331 HDD_PASSWORD_CONFIG
*IfrData
;
2332 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
2334 if (ActionRequest
!= NULL
) {
2335 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2337 return EFI_INVALID_PARAMETER
;
2340 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
2342 // Do nothing for other UEFI Action. Only do call back when data is changing or changed.
2344 return EFI_UNSUPPORTED
;
2347 Private
= HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This
);
2350 // Retrive data from Browser
2352 IfrData
= AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG
));
2353 ASSERT (IfrData
!= NULL
);
2354 if (!HiiGetBrowserData (&mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
, sizeof (HDD_PASSWORD_CONFIG
), (UINT8
*)IfrData
)) {
2356 return EFI_NOT_FOUND
;
2359 switch (QuestionId
) {
2360 case KEY_HDD_USER_PASSWORD
:
2361 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2362 DEBUG ((DEBUG_INFO
, "KEY_HDD_USER_PASSWORD\n"));
2363 ConfigFormEntry
= Private
->Current
;
2364 ConfigFormEntry
->IfrData
.Request
.UserPassword
= Value
->b
;
2365 SaveHddPasswordRequest (ConfigFormEntry
);
2366 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2370 case KEY_HDD_MASTER_PASSWORD
:
2371 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2372 DEBUG ((DEBUG_INFO
, "KEY_HDD_MASTER_PASSWORD\n"));
2373 ConfigFormEntry
= Private
->Current
;
2374 ConfigFormEntry
->IfrData
.Request
.MasterPassword
= Value
->b
;
2375 SaveHddPasswordRequest (ConfigFormEntry
);
2376 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2382 if ((QuestionId
>= KEY_HDD_DEVICE_ENTRY_BASE
) && (QuestionId
< (mNumberOfHddDevices
+ KEY_HDD_DEVICE_ENTRY_BASE
))) {
2383 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2385 // In case goto the device configuration form, update the device form title.
2387 ConfigFormEntry
= HddPasswordGetConfigFormEntryByIndex ((UINT32
)(QuestionId
- KEY_HDD_DEVICE_ENTRY_BASE
));
2388 ASSERT (ConfigFormEntry
!= NULL
);
2390 DeviceFormTitleToken
= (EFI_STRING_ID
)STR_HDD_SECURITY_HD
;
2391 HiiSetString (Private
->HiiHandle
, DeviceFormTitleToken
, ConfigFormEntry
->HddString
, NULL
);
2393 Private
->Current
= ConfigFormEntry
;
2394 CopyMem (IfrData
, &ConfigFormEntry
->IfrData
, sizeof (HDD_PASSWORD_CONFIG
));
2402 // Pass changed uncommitted data back to Form Browser
2404 HiiSetBrowserData (&mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
, sizeof (HDD_PASSWORD_CONFIG
), (UINT8
*)IfrData
, NULL
);
2411 Updates the HDD Password configuration form to add an entry for the attached
2412 ata harddisk device specified by the Controller.
2414 @param[in] HiiHandle The HII Handle associated with the registered package list.
2415 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
2416 @param[in] PciIo Pointer to PCI_IO instance.
2417 @param[in] Controller The controller handle of the attached ata controller.
2418 @param[in] Bus The bus number of ATA controller.
2419 @param[in] Device The device number of ATA controller.
2420 @param[in] Function The function number of ATA controller.
2421 @param[in] Port The port number of attached ATA device.
2422 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
2424 @retval EFI_SUCCESS The Hdd Password configuration form is updated.
2425 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2426 @retval Others Other errors as indicated.
2430 HddPasswordConfigUpdateForm (
2431 IN EFI_HII_HANDLE HiiHandle
,
2432 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
2433 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2434 IN EFI_HANDLE Controller
,
2439 IN UINT16 PortMultiplierPort
2443 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
2444 BOOLEAN EntryExisted
;
2446 VOID
*StartOpCodeHandle
;
2447 VOID
*EndOpCodeHandle
;
2448 EFI_IFR_GUID_LABEL
*StartLabel
;
2449 EFI_IFR_GUID_LABEL
*EndLabel
;
2450 CHAR16 HddString
[40];
2451 ATA_IDENTIFY_DATA IdentifyData
;
2452 EFI_DEVICE_PATH_PROTOCOL
*AtaDeviceNode
;
2454 ConfigFormEntry
= NULL
;
2455 EntryExisted
= FALSE
;
2457 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
2458 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
2460 if ((ConfigFormEntry
->Bus
== Bus
) &&
2461 (ConfigFormEntry
->Device
== Device
) &&
2462 (ConfigFormEntry
->Function
== Function
) &&
2463 (ConfigFormEntry
->Port
== Port
) &&
2464 (ConfigFormEntry
->PortMultiplierPort
== PortMultiplierPort
))
2466 EntryExisted
= TRUE
;
2471 if (!EntryExisted
) {
2475 ConfigFormEntry
= AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG_FORM_ENTRY
));
2476 if (ConfigFormEntry
== NULL
) {
2477 return EFI_OUT_OF_RESOURCES
;
2480 InitializeListHead (&ConfigFormEntry
->Link
);
2481 ConfigFormEntry
->Controller
= Controller
;
2482 ConfigFormEntry
->Bus
= Bus
;
2483 ConfigFormEntry
->Device
= Device
;
2484 ConfigFormEntry
->Function
= Function
;
2485 ConfigFormEntry
->Port
= Port
;
2486 ConfigFormEntry
->PortMultiplierPort
= PortMultiplierPort
;
2487 ConfigFormEntry
->AtaPassThru
= AtaPassThru
;
2489 DEBUG ((DEBUG_INFO
, "HddPasswordDxe: Create new form for device[%d][%d] at Bus 0x%x Dev 0x%x Func 0x%x\n", Port
, PortMultiplierPort
, Bus
, Device
, Function
));
2492 // Construct the device path for the HDD password device
2494 Status
= AtaPassThru
->BuildDevicePath (
2500 if (EFI_ERROR (Status
)) {
2504 ConfigFormEntry
->DevicePath
= AppendDevicePathNode (DevicePathFromHandle (Controller
), AtaDeviceNode
);
2505 FreePool (AtaDeviceNode
);
2506 if (ConfigFormEntry
->DevicePath
== NULL
) {
2507 return EFI_OUT_OF_RESOURCES
;
2511 // Get attached harddisk model number
2513 Status
= GetHddDeviceIdentifyData (AtaPassThru
, Port
, PortMultiplierPort
, &IdentifyData
);
2514 ASSERT_EFI_ERROR (Status
);
2515 if (EFI_ERROR (Status
)) {
2519 GetHddDeviceModelNumber (&IdentifyData
, HddString
);
2521 // Compose the HDD title string and help string of this port and create a new EFI_STRING_ID.
2523 UnicodeSPrint (ConfigFormEntry
->HddString
, sizeof (ConfigFormEntry
->HddString
), L
"HDD %d:%s", mNumberOfHddDevices
, HddString
);
2524 ConfigFormEntry
->TitleToken
= HiiSetString (HiiHandle
, 0, ConfigFormEntry
->HddString
, NULL
);
2525 ConfigFormEntry
->TitleHelpToken
= HiiSetString (HiiHandle
, 0, L
"Request to set HDD Password", NULL
);
2527 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
2529 InsertTailList (&mHddPasswordConfigFormList
, &ConfigFormEntry
->Link
);
2532 // Init OpCode Handle
2534 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2535 ASSERT (StartOpCodeHandle
!= NULL
);
2537 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2538 ASSERT (EndOpCodeHandle
!= NULL
);
2541 // Create Hii Extend Label OpCode as the start opcode
2543 StartLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
2544 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2545 StartLabel
->Number
= HDD_DEVICE_ENTRY_LABEL
;
2548 // Create Hii Extend Label OpCode as the end opcode
2550 EndLabel
= (EFI_IFR_GUID_LABEL
*)HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
2551 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2552 EndLabel
->Number
= HDD_DEVICE_LABEL_END
;
2554 mNumberOfHddDevices
= 0;
2555 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
2556 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
2558 HiiCreateGotoOpCode (
2559 StartOpCodeHandle
, // Container for dynamic created opcodes
2560 FORMID_HDD_DEVICE_FORM
, // Target Form ID
2561 ConfigFormEntry
->TitleToken
, // Prompt text
2562 ConfigFormEntry
->TitleHelpToken
, // Help text
2563 EFI_IFR_FLAG_CALLBACK
, // Question flag
2564 (UINT16
)(KEY_HDD_DEVICE_ENTRY_BASE
+ mNumberOfHddDevices
) // Question ID
2567 mNumberOfHddDevices
++;
2572 &mHddPasswordVendorGuid
,
2573 FORMID_HDD_MAIN_FORM
,
2578 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2579 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2582 // Check if device is locked and prompt for password.
2584 HddPasswordRequestPassword (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
2587 // Process HDD password request from last boot.
2589 ProcessHddPasswordRequest (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
2596 Ata Pass Thru Protocol notification event handler.
2598 Check attached harddisk status to see if it's locked. If yes, then pop up a password windows to require user input.
2599 It also registers a form for user configuration on Hdd password configuration.
2601 @param[in] Event Event whose notification function is being invoked.
2602 @param[in] Context Pointer to the notification function's context.
2607 HddPasswordNotificationEvent (
2613 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2614 EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
;
2616 UINT16 PortMultiplierPort
;
2617 EFI_HANDLE Controller
;
2618 EFI_HANDLE
*HandleBuffer
;
2621 EFI_PCI_IO_PROTOCOL
*PciIo
;
2627 if (mHddPasswordEndOfDxe
) {
2628 gBS
->CloseEvent (Event
);
2632 Private
= (HDD_PASSWORD_DXE_PRIVATE_DATA
*)Context
;
2635 // Locate all handles of AtaPassThru protocol
2637 Status
= gBS
->LocateHandleBuffer (
2639 &gEfiAtaPassThruProtocolGuid
,
2644 if (EFI_ERROR (Status
)) {
2649 // Check attached hard disk status to see if it's locked
2651 for (Index
= 0; Index
< HandleCount
; Index
+= 1) {
2652 Controller
= HandleBuffer
[Index
];
2653 Status
= gBS
->HandleProtocol (
2655 &gEfiAtaPassThruProtocolGuid
,
2656 (VOID
**)&AtaPassThru
2658 if (EFI_ERROR (Status
)) {
2663 // Ignore those logical ATA_PASS_THRU instance.
2665 if ((AtaPassThru
->Mode
->Attributes
& EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL
) == 0) {
2669 Status
= gBS
->HandleProtocol (
2671 &gEfiPciIoProtocolGuid
,
2674 ASSERT_EFI_ERROR (Status
);
2675 if (EFI_ERROR (Status
)) {
2679 Status
= PciIo
->GetLocation (
2686 ASSERT_EFI_ERROR (Status
);
2687 if (EFI_ERROR (Status
)) {
2692 // Assume and only support Segment == 0.
2694 ASSERT (SegNum
== 0);
2697 // traverse all attached harddisk devices to update form and unlock it
2702 Status
= AtaPassThru
->GetNextPort (AtaPassThru
, &Port
);
2703 if (EFI_ERROR (Status
)) {
2705 // We cannot find more legal port then we are done.
2710 PortMultiplierPort
= 0xFFFF;
2712 Status
= AtaPassThru
->GetNextDevice (AtaPassThru
, Port
, &PortMultiplierPort
);
2713 if (EFI_ERROR (Status
)) {
2715 // We cannot find more legal port multiplier port number for ATA device
2716 // on the port, then we are done.
2722 // Find out the attached harddisk devices.
2723 // Try to add a HDD Password configuration page for the attached devices.
2725 gBS
->RestoreTPL (TPL_APPLICATION
);
2726 Status
= HddPasswordConfigUpdateForm (Private
->HiiHandle
, AtaPassThru
, PciIo
, Controller
, BusNum
, DevNum
, FuncNum
, Port
, PortMultiplierPort
);
2727 gBS
->RaiseTPL (TPL_CALLBACK
);
2728 if (EFI_ERROR (Status
)) {
2735 FreePool (HandleBuffer
);
2740 Initialize the HDD Password configuration form.
2742 @param[out] Instance Pointer to private instance.
2744 @retval EFI_SUCCESS The HDD Password configuration form is initialized.
2745 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2746 @retval Others Other errors as indicated.
2749 HddPasswordConfigFormInit (
2750 OUT HDD_PASSWORD_DXE_PRIVATE_DATA
**Instance
2754 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2756 InitializeListHead (&mHddPasswordConfigFormList
);
2758 Private
= AllocateZeroPool (sizeof (HDD_PASSWORD_DXE_PRIVATE_DATA
));
2759 if (Private
== NULL
) {
2760 return EFI_OUT_OF_RESOURCES
;
2763 Private
->Signature
= HDD_PASSWORD_DXE_PRIVATE_SIGNATURE
;
2765 Private
->ConfigAccess
.ExtractConfig
= HddPasswordFormExtractConfig
;
2766 Private
->ConfigAccess
.RouteConfig
= HddPasswordFormRouteConfig
;
2767 Private
->ConfigAccess
.Callback
= HddPasswordFormCallback
;
2770 // Install Device Path Protocol and Config Access protocol to driver handle
2772 Status
= gBS
->InstallMultipleProtocolInterfaces (
2773 &Private
->DriverHandle
,
2774 &gEfiDevicePathProtocolGuid
,
2775 &mHddPasswordHiiVendorDevicePath
,
2776 &gEfiHiiConfigAccessProtocolGuid
,
2777 &Private
->ConfigAccess
,
2780 ASSERT_EFI_ERROR (Status
);
2781 if (EFI_ERROR (Status
)) {
2787 // Publish our HII data
2789 Private
->HiiHandle
= HiiAddPackages (
2790 &mHddPasswordVendorGuid
,
2791 Private
->DriverHandle
,
2792 HddPasswordDxeStrings
,
2796 if (Private
->HiiHandle
== NULL
) {
2798 return EFI_OUT_OF_RESOURCES
;
2801 *Instance
= Private
;
2806 Main entry for this driver.
2808 @param ImageHandle Image handle this driver.
2809 @param SystemTable Pointer to SystemTable.
2811 @retval EFI_SUCCESS This function always complete successfully.
2816 HddPasswordDxeInit (
2817 IN EFI_HANDLE ImageHandle
,
2818 IN EFI_SYSTEM_TABLE
*SystemTable
2822 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2824 EFI_EVENT EndOfDxeEvent
;
2825 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
2830 // Initialize the configuration form of HDD Password.
2832 Status
= HddPasswordConfigFormInit (&Private
);
2833 if (EFI_ERROR (Status
)) {
2838 // Register HddPasswordNotificationEvent() notify function.
2840 EfiCreateProtocolNotifyEvent (
2841 &gEfiAtaPassThruProtocolGuid
,
2843 HddPasswordNotificationEvent
,
2848 Status
= gBS
->CreateEventEx (
2851 HddPasswordEndOfDxeEventNotify
,
2853 &gEfiEndOfDxeEventGroupGuid
,
2856 ASSERT_EFI_ERROR (Status
);
2859 // Make HDD_PASSWORD_VARIABLE_NAME variable read-only.
2861 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**)&VariableLock
);
2862 if (!EFI_ERROR (Status
)) {
2863 Status
= VariableLock
->RequestToLock (
2865 HDD_PASSWORD_VARIABLE_NAME
,
2866 &mHddPasswordVendorGuid
2868 DEBUG ((DEBUG_INFO
, "%a(): Lock %s variable (%r)\n", __FUNCTION__
, HDD_PASSWORD_VARIABLE_NAME
, Status
));
2869 ASSERT_EFI_ERROR (Status
);