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)
47 Check if the password is full zero.
49 @param[in] Password Points to the data buffer
51 @retval TRUE This password string is full zero.
52 @retval FALSE This password string is not full zero.
62 for (Index
= 0; Index
< HDD_PASSWORD_MAX_LENGTH
; Index
++) {
63 if (Password
[Index
] != 0) {
74 @param[in] ConfigFormEntry Points to HDD_PASSWORD_CONFIG_FORM_ENTRY buffer
75 @param[in,out] TempDevInfo Points to HDD_PASSWORD_DEVICE_INFO buffer
80 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
81 IN OUT HDD_PASSWORD_DEVICE_INFO
*TempDevInfo
84 TempDevInfo
->Device
.Bus
= (UINT8
) ConfigFormEntry
->Bus
;
85 TempDevInfo
->Device
.Device
= (UINT8
) ConfigFormEntry
->Device
;
86 TempDevInfo
->Device
.Function
= (UINT8
) ConfigFormEntry
->Function
;
87 TempDevInfo
->Device
.Port
= ConfigFormEntry
->Port
;
88 TempDevInfo
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
89 CopyMem (TempDevInfo
->Password
, ConfigFormEntry
->Password
, HDD_PASSWORD_MAX_LENGTH
);
90 TempDevInfo
->DevicePathLength
= (UINT32
) GetDevicePathSize (ConfigFormEntry
->DevicePath
);
91 CopyMem (TempDevInfo
->DevicePath
, ConfigFormEntry
->DevicePath
, TempDevInfo
->DevicePathLength
);
95 Build HDD password device info and save them to LockBox.
99 BuildHddPasswordDeviceInfo (
105 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
106 HDD_PASSWORD_DEVICE_INFO
*DevInfo
;
107 HDD_PASSWORD_DEVICE_INFO
*TempDevInfo
;
110 BOOLEAN S3InitDevicesExist
;
111 UINTN S3InitDevicesLength
;
112 EFI_DEVICE_PATH_PROTOCOL
*S3InitDevices
;
113 EFI_DEVICE_PATH_PROTOCOL
*S3InitDevicesBak
;
116 // Build HDD password device info and save them to LockBox.
119 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
120 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
123 // 1. Handle device which already set password.
124 // 2. When request to send freeze command, driver also needs to handle device
125 // which support security feature.
127 if ((!PasswordIsFullZero (ConfigFormEntry
->Password
)) ||
128 ((ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
!= 0) &&
129 (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))) {
174 SaveDeviceInfo (ConfigFormEntry
, TempDevInfo
);
176 S3InitDevicesBak
= S3InitDevices
;
177 S3InitDevices
= AppendDevicePathInstance (
179 ConfigFormEntry
->DevicePath
181 if (S3InitDevicesBak
!= NULL
) {
182 FreePool (S3InitDevicesBak
);
184 ASSERT (S3InitDevices
!= NULL
);
186 TempDevInfo
= (HDD_PASSWORD_DEVICE_INFO
*) ((UINTN
)TempDevInfo
+
187 sizeof (HDD_PASSWORD_DEVICE_INFO
) +
188 TempDevInfo
->DevicePathLength
);
192 Status
= SaveLockBox (
193 &mHddPasswordDeviceInfoGuid
,
197 ASSERT_EFI_ERROR (Status
);
199 Status
= SetLockBoxAttributes (
200 &mHddPasswordDeviceInfoGuid
,
201 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
203 ASSERT_EFI_ERROR (Status
);
205 S3InitDevicesLength
= GetDevicePathSize (S3InitDevices
);
206 if (S3InitDevicesExist
) {
207 Status
= UpdateLockBox (
208 &gS3StorageDeviceInitListGuid
,
213 ASSERT_EFI_ERROR (Status
);
215 Status
= SaveLockBox (
216 &gS3StorageDeviceInitListGuid
,
220 ASSERT_EFI_ERROR (Status
);
222 Status
= SetLockBoxAttributes (
223 &gS3StorageDeviceInitListGuid
,
224 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
226 ASSERT_EFI_ERROR (Status
);
229 ZeroMem (DevInfo
, DevInfoLength
);
231 FreePool (S3InitDevices
);
235 Send freeze lock cmd through Ata Pass Thru Protocol.
237 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
238 @param[in] Port The port number of the ATA device to send the command.
239 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
240 If there is no port multiplier, then specify 0xFFFF.
242 @retval EFI_SUCCESS Successful to send freeze lock cmd.
243 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
244 @retval EFI_OUT_OF_RESOURCES Not enough memory to send freeze lock cmd.
245 @retval EFI_DEVICE_ERROR Can not send freeze lock cmd.
250 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
252 IN UINT16 PortMultiplierPort
256 EFI_ATA_COMMAND_BLOCK Acb
;
257 EFI_ATA_STATUS_BLOCK
*Asb
;
258 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
260 if (AtaPassThru
== NULL
) {
261 return EFI_INVALID_PARAMETER
;
265 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
266 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
267 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
268 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
269 // may not be aligned when allocated on stack for some compilers. Hence, we
270 // use the API AllocateAlignedPages to ensure this structure is properly
273 Asb
= AllocateAlignedPages (
274 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
275 AtaPassThru
->Mode
->IoAlign
278 return EFI_OUT_OF_RESOURCES
;
282 // Prepare for ATA command block.
284 ZeroMem (&Acb
, sizeof (Acb
));
285 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
286 Acb
.AtaCommand
= ATA_SECURITY_FREEZE_LOCK_CMD
;
287 Acb
.AtaDeviceHead
= (UINT8
) (PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
290 // Prepare for ATA pass through packet.
292 ZeroMem (&Packet
, sizeof (Packet
));
293 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA
;
294 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_NO_DATA_TRANSFER
;
297 Packet
.Timeout
= ATA_TIMEOUT
;
299 Status
= AtaPassThru
->PassThru (
306 if (!EFI_ERROR (Status
) &&
307 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
308 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0)) {
309 Status
= EFI_DEVICE_ERROR
;
312 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
314 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
319 Get attached harddisk identify data through Ata Pass Thru Protocol.
321 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
322 @param[in] Port The port number of the ATA device to send the command.
323 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
324 If there is no port multiplier, then specify 0xFFFF.
325 @param[in] IdentifyData The buffer to store identify data.
327 @retval EFI_SUCCESS Successful to get identify data.
328 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
329 @retval EFI_OUT_OF_RESOURCES Not enough memory to get identify data.
330 @retval EFI_DEVICE_ERROR Can not get identify data.
334 GetHddDeviceIdentifyData (
335 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
337 IN UINT16 PortMultiplierPort
,
338 IN ATA_IDENTIFY_DATA
*IdentifyData
342 EFI_ATA_COMMAND_BLOCK Acb
;
343 EFI_ATA_STATUS_BLOCK
*Asb
;
344 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
346 if ((AtaPassThru
== NULL
) || (IdentifyData
== NULL
)) {
347 return EFI_INVALID_PARAMETER
;
351 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
352 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
353 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
354 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
355 // may not be aligned when allocated on stack for some compilers. Hence, we
356 // use the API AllocateAlignedPages to ensure this structure is properly
359 Asb
= AllocateAlignedPages (
360 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
361 AtaPassThru
->Mode
->IoAlign
364 return EFI_OUT_OF_RESOURCES
;
368 // Prepare for ATA command block.
370 ZeroMem (&Acb
, sizeof (Acb
));
371 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
372 Acb
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
373 Acb
.AtaDeviceHead
= (UINT8
) (BIT7
| BIT6
| BIT5
| (PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4)));
376 // Prepare for ATA pass through packet.
378 ZeroMem (&Packet
, sizeof (Packet
));
379 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN
;
380 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
| EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT
;
383 Packet
.InDataBuffer
= IdentifyData
;
384 Packet
.InTransferLength
= sizeof (ATA_IDENTIFY_DATA
);
385 Packet
.Timeout
= ATA_TIMEOUT
;
387 Status
= AtaPassThru
->PassThru (
395 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
401 Parse security status according to identify data.
403 @param[in] IdentifyData The buffer to store identify data.
404 @param[in, out] IfrData IFR data to hold security status.
408 GetHddPasswordSecurityStatus (
409 IN ATA_IDENTIFY_DATA
*IdentifyData
,
410 IN OUT HDD_PASSWORD_CONFIG
*IfrData
413 IfrData
->SecurityStatus
.Supported
= (IdentifyData
->command_set_supported_82
& BIT1
) ? 1 : 0;
414 IfrData
->SecurityStatus
.Enabled
= (IdentifyData
->security_status
& BIT1
) ? 1 : 0;
415 IfrData
->SecurityStatus
.Locked
= (IdentifyData
->security_status
& BIT2
) ? 1 : 0;
416 IfrData
->SecurityStatus
.Frozen
= (IdentifyData
->security_status
& BIT3
) ? 1 : 0;
417 IfrData
->SecurityStatus
.UserPasswordStatus
= IfrData
->SecurityStatus
.Enabled
;
418 IfrData
->SecurityStatus
.MasterPasswordStatus
= IfrData
->SecurityStatus
.Supported
;
420 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Supported = %x\n", IfrData
->SecurityStatus
.Supported
));
421 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Enabled = %x\n", IfrData
->SecurityStatus
.Enabled
));
422 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Locked = %x\n", IfrData
->SecurityStatus
.Locked
));
423 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.Frozen = %x\n", IfrData
->SecurityStatus
.Frozen
));
424 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.UserPasswordStatus = %x\n", IfrData
->SecurityStatus
.UserPasswordStatus
));
425 DEBUG ((DEBUG_INFO
, "IfrData->SecurityStatus.MasterPasswordStatus = %x\n", IfrData
->SecurityStatus
.MasterPasswordStatus
));
429 Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
431 This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
433 @param Event Event whose notification function is being invoked.
434 @param Context Pointer to the notification function's context.
439 HddPasswordEndOfDxeEventNotify (
445 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
447 ATA_IDENTIFY_DATA IdentifyData
;
449 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
451 mHddPasswordEndOfDxe
= TRUE
;
453 if (mHddPasswordRequestVariable
!= NULL
) {
455 // Free the HDD password request variable buffer here
456 // as the HDD password requests should have been processed.
458 FreePool (mHddPasswordRequestVariable
);
459 mHddPasswordRequestVariable
= NULL
;
460 mHddPasswordRequestVariableSize
= 0;
464 // If no any device, return directly.
466 if (IsListEmpty (&mHddPasswordConfigFormList
)) {
467 gBS
->CloseEvent (Event
);
471 BuildHddPasswordDeviceInfo ();
474 // Zero passsword and freeze lock device.
476 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
477 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
479 ZeroMem (ConfigFormEntry
->Password
, HDD_PASSWORD_MAX_LENGTH
);
482 // Check whether need send freeze lock command.
483 // Below device will be froze:
484 // 1. Device not enable password.
485 // 2. Device enable password and unlocked.
487 if ((ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
!= 0) &&
488 (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
== 0) &&
489 (ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
== 0)) {
490 Status
= FreezeLockDevice (ConfigFormEntry
->AtaPassThru
, ConfigFormEntry
->Port
, ConfigFormEntry
->PortMultiplierPort
);
491 DEBUG ((DEBUG_INFO
, "FreezeLockDevice return %r!\n", Status
));
492 Status
= GetHddDeviceIdentifyData (
493 ConfigFormEntry
->AtaPassThru
,
494 ConfigFormEntry
->Port
,
495 ConfigFormEntry
->PortMultiplierPort
,
498 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
502 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
504 gBS
->CloseEvent (Event
);
510 @param[in, out] SaltValue Points to the salt buffer, 32 bytes
515 IN OUT UINT8
*SaltValue
518 RandomSeed (NULL
, 0);
519 RandomBytes (SaltValue
, PASSWORD_SALT_SIZE
);
523 Hash the data to get credential.
525 @param[in] Buffer Points to the data buffer
526 @param[in] BufferSize Buffer size
527 @param[in] SaltValue Points to the salt buffer, 32 bytes
528 @param[out] Credential Points to the hashed result
530 @retval TRUE Hash the data successfully.
531 @retval FALSE Failed to hash the data.
539 OUT UINT8
*Credential
551 HashSize
= Sha256GetContextSize ();
552 Hash
= AllocateZeroPool (HashSize
);
553 ASSERT (Hash
!= NULL
);
558 Status
= Sha256Init (Hash
);
563 HashData
= AllocateZeroPool (PASSWORD_SALT_SIZE
+ BufferSize
);
564 ASSERT (HashData
!= NULL
);
565 if (HashData
== NULL
) {
569 CopyMem (HashData
, SaltValue
, PASSWORD_SALT_SIZE
);
570 CopyMem ((UINT8
*) HashData
+ PASSWORD_SALT_SIZE
, Buffer
, BufferSize
);
572 Status
= Sha256Update (Hash
, HashData
, PASSWORD_SALT_SIZE
+ BufferSize
);
577 Status
= Sha256Final (Hash
, Credential
);
583 if (HashData
!= NULL
) {
584 ZeroMem (HashData
, PASSWORD_SALT_SIZE
+ BufferSize
);
591 Save HDD password variable that will be used to validate HDD password
592 when the device is at frozen state.
594 @param[in] ConfigFormEntry The HDD Password configuration form entry.
595 @param[in] Password The hdd password of attached ATA device.
599 SaveHddPasswordVariable (
600 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
605 HDD_PASSWORD_VARIABLE
*TempVariable
;
606 UINTN TempVariableSize
;
607 HDD_PASSWORD_VARIABLE
*NextNode
;
608 HDD_PASSWORD_VARIABLE
*Variable
;
610 HDD_PASSWORD_VARIABLE
*NewVariable
;
611 UINTN NewVariableSize
;
614 UINT8 HashData
[SHA256_DIGEST_SIZE
];
615 UINT8 SaltData
[PASSWORD_SALT_SIZE
];
617 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
620 if (!PasswordIsFullZero (Password
)) {
622 // It is Set/Update HDD Password.
624 ZeroMem (HashData
, sizeof (HashData
));
625 ZeroMem (SaltData
, sizeof (SaltData
));
627 HashOk
= GenerateCredential ((UINT8
*) Password
, HDD_PASSWORD_MAX_LENGTH
, SaltData
, HashData
);
629 DEBUG ((DEBUG_INFO
, "GenerateCredential failed\n"));
634 // It is Disable HDD Password.
635 // Go to delete the variable node for the HDD password device.
645 Status
= GetVariable2 (
646 HDD_PASSWORD_VARIABLE_NAME
,
647 &mHddPasswordVendorGuid
,
652 if (!EFI_ERROR (Status
) && (Variable
!= NULL
)) {
653 TempVariable
= Variable
;
654 TempVariableSize
= VariableSize
;
655 while (TempVariableSize
>= sizeof (HDD_PASSWORD_VARIABLE
)) {
656 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
657 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
658 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
659 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
660 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
)) {
662 // Found the node for the HDD password device.
665 NextNode
= TempVariable
+ 1;
666 CopyMem (TempVariable
, NextNode
, (UINTN
) Variable
+ VariableSize
- (UINTN
) NextNode
);
667 NewVariable
= Variable
;
668 NewVariableSize
= VariableSize
- sizeof (HDD_PASSWORD_VARIABLE
);
671 TempVariableSize
-= sizeof (HDD_PASSWORD_VARIABLE
);
674 if (NewVariable
== NULL
) {
675 DEBUG ((DEBUG_INFO
, "The variable node for the HDD password device is not found\n"));
678 DEBUG ((DEBUG_INFO
, "HddPassword variable get failed (%r)\n", Status
));
681 if (!EFI_ERROR (Status
) && (Variable
!= NULL
)) {
682 TempVariable
= Variable
;
683 TempVariableSize
= VariableSize
;
684 while (TempVariableSize
>= sizeof (HDD_PASSWORD_VARIABLE
)) {
685 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
686 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
687 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
688 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
689 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
)) {
691 // Found the node for the HDD password device.
694 CopyMem (TempVariable
->PasswordHash
, HashData
, sizeof (HashData
));
695 CopyMem (TempVariable
->PasswordSalt
, SaltData
, sizeof (SaltData
));
696 NewVariable
= Variable
;
697 NewVariableSize
= VariableSize
;
700 TempVariableSize
-= sizeof (HDD_PASSWORD_VARIABLE
);
703 if (NewVariable
== NULL
) {
705 // The node for the HDD password device is not found.
706 // Create node for the HDD password device.
708 NewVariableSize
= VariableSize
+ sizeof (HDD_PASSWORD_VARIABLE
);
709 NewVariable
= AllocateZeroPool (NewVariableSize
);
710 ASSERT (NewVariable
!= NULL
);
711 CopyMem (NewVariable
, Variable
, VariableSize
);
712 TempVariable
= (HDD_PASSWORD_VARIABLE
*) ((UINTN
) NewVariable
+ VariableSize
);
713 TempVariable
->Device
.Bus
= (UINT8
) ConfigFormEntry
->Bus
;
714 TempVariable
->Device
.Device
= (UINT8
) ConfigFormEntry
->Device
;
715 TempVariable
->Device
.Function
= (UINT8
) ConfigFormEntry
->Function
;
716 TempVariable
->Device
.Port
= ConfigFormEntry
->Port
;
717 TempVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
718 CopyMem (TempVariable
->PasswordHash
, HashData
, sizeof (HashData
));
719 CopyMem (TempVariable
->PasswordSalt
, SaltData
, sizeof (SaltData
));
722 NewVariableSize
= sizeof (HDD_PASSWORD_VARIABLE
);
723 NewVariable
= AllocateZeroPool (NewVariableSize
);
724 ASSERT (NewVariable
!= NULL
);
725 NewVariable
->Device
.Bus
= (UINT8
) ConfigFormEntry
->Bus
;
726 NewVariable
->Device
.Device
= (UINT8
) ConfigFormEntry
->Device
;
727 NewVariable
->Device
.Function
= (UINT8
) ConfigFormEntry
->Function
;
728 NewVariable
->Device
.Port
= ConfigFormEntry
->Port
;
729 NewVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
730 CopyMem (NewVariable
->PasswordHash
, HashData
, sizeof (HashData
));
731 CopyMem (NewVariable
->PasswordSalt
, SaltData
, sizeof (SaltData
));
735 if (NewVariable
!= NULL
) {
736 Status
= gRT
->SetVariable (
737 HDD_PASSWORD_VARIABLE_NAME
,
738 &mHddPasswordVendorGuid
,
739 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
743 if (EFI_ERROR (Status
)) {
744 DEBUG ((DEBUG_INFO
, "HddPassword variable set failed (%r)\n", Status
));
748 if (NewVariable
!= Variable
) {
749 FreePool (NewVariable
);
751 if (Variable
!= NULL
) {
755 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
759 Get saved HDD password variable that will be used to validate HDD password
760 when the device is at frozen state.
762 @param[in] ConfigFormEntry The HDD Password configuration form entry.
763 @param[out] HddPasswordVariable The variable node for the HDD password device.
765 @retval TRUE The variable node for the HDD password device is found and returned.
766 @retval FALSE The variable node for the HDD password device is not found.
770 GetSavedHddPasswordVariable (
771 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
772 OUT HDD_PASSWORD_VARIABLE
*HddPasswordVariable
776 HDD_PASSWORD_VARIABLE
*TempVariable
;
777 HDD_PASSWORD_VARIABLE
*Variable
;
781 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
786 Status
= GetVariable2 (
787 HDD_PASSWORD_VARIABLE_NAME
,
788 &mHddPasswordVendorGuid
,
792 if (EFI_ERROR (Status
) || (Variable
== NULL
)) {
793 DEBUG ((DEBUG_INFO
, "HddPassword variable get failed (%r)\n", Status
));
798 TempVariable
= Variable
;
799 while (VariableSize
>= sizeof (HDD_PASSWORD_VARIABLE
)) {
800 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
801 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
802 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
803 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
804 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
)) {
806 // Found the node for the HDD password device.
809 CopyMem (HddPasswordVariable
, TempVariable
, sizeof (HDD_PASSWORD_VARIABLE
));
813 VariableSize
-= sizeof (HDD_PASSWORD_VARIABLE
);
820 DEBUG ((DEBUG_INFO
, "The variable node for the HDD password device is not found\n"));
823 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
829 Use saved HDD password variable to validate HDD password
830 when the device is at frozen state.
832 @param[in] ConfigFormEntry The HDD Password configuration form entry.
833 @param[in] Password The hdd password of attached ATA device.
835 @retval EFI_SUCCESS Pass to validate the HDD password.
836 @retval EFI_NOT_FOUND The variable node for the HDD password device is not found.
837 @retval EFI_DEVICE_ERROR Failed to generate credential for the HDD password.
838 @retval EFI_INVALID_PARAMETER Failed to validate the HDD password.
842 ValidateHddPassword (
843 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
848 HDD_PASSWORD_VARIABLE HddPasswordVariable
;
850 UINT8 HashData
[SHA256_DIGEST_SIZE
];
852 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
854 if (!GetSavedHddPasswordVariable (ConfigFormEntry
, &HddPasswordVariable
)) {
855 DEBUG ((DEBUG_INFO
, "GetSavedHddPasswordVariable failed\n"));
856 return EFI_NOT_FOUND
;
859 ZeroMem (HashData
, sizeof (HashData
));
860 HashOk
= GenerateCredential ((UINT8
*) Password
, HDD_PASSWORD_MAX_LENGTH
, HddPasswordVariable
.PasswordSalt
, HashData
);
862 DEBUG ((DEBUG_INFO
, "GenerateCredential failed\n"));
863 return EFI_DEVICE_ERROR
;
866 if (CompareMem (HddPasswordVariable
.PasswordHash
, HashData
, sizeof (HashData
)) != 0) {
867 Status
= EFI_INVALID_PARAMETER
;
869 Status
= EFI_SUCCESS
;
872 DEBUG ((DEBUG_INFO
, "%a() - exit (%r)\n", __FUNCTION__
, Status
));
877 Send unlock hdd password cmd through Ata Pass Thru Protocol.
879 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
880 @param[in] Port The port number of the ATA device to send the command.
881 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
882 If there is no port multiplier, then specify 0xFFFF.
883 @param[in] Identifier The identifier to set user or master password.
884 @param[in] Password The hdd password of attached ATA device.
886 @retval EFI_SUCCESS Successful to send unlock hdd password cmd.
887 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
888 @retval EFI_OUT_OF_RESOURCES Not enough memory to send unlock hdd password cmd.
889 @retval EFI_DEVICE_ERROR Can not send unlock hdd password cmd.
894 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
896 IN UINT16 PortMultiplierPort
,
902 EFI_ATA_COMMAND_BLOCK Acb
;
903 EFI_ATA_STATUS_BLOCK
*Asb
;
904 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
905 UINT8 Buffer
[HDD_PAYLOAD
];
907 if ((AtaPassThru
== NULL
) || (Password
== NULL
)) {
908 return EFI_INVALID_PARAMETER
;
912 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
913 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
914 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
915 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
916 // may not be aligned when allocated on stack for some compilers. Hence, we
917 // use the API AllocateAlignedPages to ensure this structure is properly
920 Asb
= AllocateAlignedPages (
921 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
922 AtaPassThru
->Mode
->IoAlign
925 return EFI_OUT_OF_RESOURCES
;
929 // Prepare for ATA command block.
931 ZeroMem (&Acb
, sizeof (Acb
));
932 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
933 Acb
.AtaCommand
= ATA_SECURITY_UNLOCK_CMD
;
934 Acb
.AtaDeviceHead
= (UINT8
) (PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
937 // Prepare for ATA pass through packet.
939 ZeroMem (&Packet
, sizeof (Packet
));
940 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
;
941 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
945 ((CHAR16
*) Buffer
)[0] = Identifier
& BIT0
;
946 CopyMem (&((CHAR16
*) Buffer
)[1], Password
, HDD_PASSWORD_MAX_LENGTH
);
948 Packet
.OutDataBuffer
= Buffer
;
949 Packet
.OutTransferLength
= sizeof (Buffer
);
950 Packet
.Timeout
= ATA_TIMEOUT
;
952 Status
= AtaPassThru
->PassThru (
959 if (!EFI_ERROR (Status
) &&
960 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
961 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0)) {
962 Status
= EFI_DEVICE_ERROR
;
965 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
967 ZeroMem (Buffer
, sizeof (Buffer
));
969 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
974 Send disable hdd password cmd through Ata Pass Thru Protocol.
976 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
977 @param[in] Port The port number of the ATA device to send the command.
978 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
979 If there is no port multiplier, then specify 0xFFFF.
980 @param[in] Identifier The identifier to set user or master password.
981 @param[in] Password The hdd password of attached ATA device.
983 @retval EFI_SUCCESS Successful to disable hdd password cmd.
984 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
985 @retval EFI_OUT_OF_RESOURCES Not enough memory to disable hdd password cmd.
986 @retval EFI_DEVICE_ERROR Can not disable hdd password cmd.
991 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
993 IN UINT16 PortMultiplierPort
,
999 EFI_ATA_COMMAND_BLOCK Acb
;
1000 EFI_ATA_STATUS_BLOCK
*Asb
;
1001 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
1002 UINT8 Buffer
[HDD_PAYLOAD
];
1004 if ((AtaPassThru
== NULL
) || (Password
== NULL
)) {
1005 return EFI_INVALID_PARAMETER
;
1009 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
1010 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
1011 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
1012 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
1013 // may not be aligned when allocated on stack for some compilers. Hence, we
1014 // use the API AllocateAlignedPages to ensure this structure is properly
1017 Asb
= AllocateAlignedPages (
1018 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
1019 AtaPassThru
->Mode
->IoAlign
1022 return EFI_OUT_OF_RESOURCES
;
1026 // Prepare for ATA command block.
1028 ZeroMem (&Acb
, sizeof (Acb
));
1029 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
1030 Acb
.AtaCommand
= ATA_SECURITY_DIS_PASSWORD_CMD
;
1031 Acb
.AtaDeviceHead
= (UINT8
) (PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
1034 // Prepare for ATA pass through packet.
1036 ZeroMem (&Packet
, sizeof (Packet
));
1037 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
;
1038 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
1042 ((CHAR16
*) Buffer
)[0] = Identifier
& BIT0
;
1043 CopyMem (&((CHAR16
*) Buffer
)[1], Password
, HDD_PASSWORD_MAX_LENGTH
);
1045 Packet
.OutDataBuffer
= Buffer
;
1046 Packet
.OutTransferLength
= sizeof (Buffer
);
1047 Packet
.Timeout
= ATA_TIMEOUT
;
1049 Status
= AtaPassThru
->PassThru (
1056 if (!EFI_ERROR (Status
) &&
1057 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
1058 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0)) {
1059 Status
= EFI_DEVICE_ERROR
;
1062 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
1064 ZeroMem (Buffer
, sizeof (Buffer
));
1066 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
1071 Send set hdd password cmd through Ata Pass Thru Protocol.
1073 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.
1074 @param[in] Port The port number of the ATA device to send the command.
1075 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
1076 If there is no port multiplier, then specify 0xFFFF.
1077 @param[in] Identifier The identifier to set user or master password.
1078 @param[in] SecurityLevel The security level to be set to device.
1079 @param[in] MasterPasswordIdentifier The master password identifier to be set to device.
1080 @param[in] Password The hdd password of attached ATA device.
1082 @retval EFI_SUCCESS Successful to set hdd password cmd.
1083 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.
1084 @retval EFI_OUT_OF_RESOURCES Not enough memory to set hdd password cmd.
1085 @retval EFI_DEVICE_ERROR Can not set hdd password cmd.
1090 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1092 IN UINT16 PortMultiplierPort
,
1093 IN CHAR8 Identifier
,
1094 IN CHAR8 SecurityLevel
,
1095 IN CHAR16 MasterPasswordIdentifier
,
1100 EFI_ATA_COMMAND_BLOCK Acb
;
1101 EFI_ATA_STATUS_BLOCK
*Asb
;
1102 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
1103 UINT8 Buffer
[HDD_PAYLOAD
];
1105 if ((AtaPassThru
== NULL
) || (Password
== NULL
)) {
1106 return EFI_INVALID_PARAMETER
;
1110 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in
1111 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by
1112 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,
1113 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it
1114 // may not be aligned when allocated on stack for some compilers. Hence, we
1115 // use the API AllocateAlignedPages to ensure this structure is properly
1118 Asb
= AllocateAlignedPages (
1119 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)),
1120 AtaPassThru
->Mode
->IoAlign
1123 return EFI_OUT_OF_RESOURCES
;
1127 // Prepare for ATA command block.
1129 ZeroMem (&Acb
, sizeof (Acb
));
1130 ZeroMem (Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
1131 Acb
.AtaCommand
= ATA_SECURITY_SET_PASSWORD_CMD
;
1132 Acb
.AtaDeviceHead
= (UINT8
) (PortMultiplierPort
== 0xFFFF ? 0 : (PortMultiplierPort
<< 4));
1135 // Prepare for ATA pass through packet.
1137 ZeroMem (&Packet
, sizeof (Packet
));
1138 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
;
1139 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
1143 ((CHAR16
*) Buffer
)[0] = (Identifier
| (UINT16
)(SecurityLevel
<< 8)) & (BIT0
| BIT8
);
1144 CopyMem (&((CHAR16
*) Buffer
)[1], Password
, HDD_PASSWORD_MAX_LENGTH
);
1145 if ((Identifier
& BIT0
) != 0) {
1146 ((CHAR16
*) Buffer
)[17] = MasterPasswordIdentifier
;
1149 Packet
.OutDataBuffer
= Buffer
;
1150 Packet
.OutTransferLength
= sizeof (Buffer
);
1151 Packet
.Timeout
= ATA_TIMEOUT
;
1153 Status
= AtaPassThru
->PassThru (
1160 if (!EFI_ERROR (Status
) &&
1161 ((Asb
->AtaStatus
& ATA_STSREG_ERR
) != 0) &&
1162 ((Asb
->AtaError
& ATA_ERRREG_ABRT
) != 0)) {
1163 Status
= EFI_DEVICE_ERROR
;
1166 FreeAlignedPages (Asb
, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK
)));
1168 ZeroMem (Buffer
, sizeof (Buffer
));
1170 DEBUG ((DEBUG_INFO
, "%a() - %r\n", __FUNCTION__
, Status
));
1175 Get attached harddisk model number from identify data buffer.
1177 @param[in] IdentifyData Pointer to identify data buffer.
1178 @param[in, out] String The buffer to store harddisk model number.
1182 GetHddDeviceModelNumber (
1183 IN ATA_IDENTIFY_DATA
*IdentifyData
,
1184 IN OUT CHAR16
*String
1190 // Swap the byte order in the original module name.
1191 // From Ata spec, the maximum length is 40 bytes.
1193 for (Index
= 0; Index
< 40; Index
+= 2) {
1194 String
[Index
] = IdentifyData
->ModelName
[Index
+ 1];
1195 String
[Index
+ 1] = IdentifyData
->ModelName
[Index
];
1199 // Chap it off after 20 characters
1207 Get password input from the popup windows.
1209 @param[in] PopUpString1 Pop up string 1.
1210 @param[in] PopUpString2 Pop up string 2.
1211 @param[in, out] Password The buffer to hold the input password.
1213 @retval EFI_ABORTED It is given up by pressing 'ESC' key.
1214 @retval EFI_SUCCESS Get password input successfully.
1218 PopupHddPasswordInputWindows (
1219 IN CHAR16
*PopUpString1
,
1220 IN CHAR16
*PopUpString2
,
1221 IN OUT CHAR8
*Password
1226 CHAR16 Mask
[HDD_PASSWORD_MAX_LENGTH
+ 1];
1227 CHAR16 Unicode
[HDD_PASSWORD_MAX_LENGTH
+ 1];
1228 CHAR8 Ascii
[HDD_PASSWORD_MAX_LENGTH
+ 1];
1230 ZeroMem (Unicode
, sizeof (Unicode
));
1231 ZeroMem (Ascii
, sizeof (Ascii
));
1232 ZeroMem (Mask
, sizeof (Mask
));
1234 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1238 Mask
[Length
] = L
'_';
1239 if (PopUpString2
== NULL
) {
1241 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1244 L
"---------------------",
1250 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1254 L
"---------------------",
1262 if (Key
.ScanCode
== SCAN_NULL
) {
1263 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1265 // Add the null terminator.
1267 Unicode
[Length
] = 0;
1269 } else if ((Key
.UnicodeChar
== CHAR_NULL
) ||
1270 (Key
.UnicodeChar
== CHAR_TAB
) ||
1271 (Key
.UnicodeChar
== CHAR_LINEFEED
)
1275 if (Key
.UnicodeChar
== CHAR_BACKSPACE
) {
1277 Unicode
[Length
] = 0;
1282 Unicode
[Length
] = Key
.UnicodeChar
;
1283 Mask
[Length
] = L
'*';
1285 if (Length
== HDD_PASSWORD_MAX_LENGTH
) {
1287 // Add the null terminator.
1289 Unicode
[Length
] = 0;
1297 if (Key
.ScanCode
== SCAN_ESC
) {
1298 ZeroMem (Unicode
, sizeof (Unicode
));
1299 ZeroMem (Ascii
, sizeof (Ascii
));
1300 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1305 UnicodeStrToAsciiStrS (Unicode
, Ascii
, sizeof (Ascii
));
1306 CopyMem (Password
, Ascii
, HDD_PASSWORD_MAX_LENGTH
);
1307 ZeroMem (Unicode
, sizeof (Unicode
));
1308 ZeroMem (Ascii
, sizeof (Ascii
));
1310 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1315 Check if disk is locked, show popup window and ask for password if it is.
1317 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1318 @param[in] Port The port number of attached ATA device.
1319 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1320 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1324 HddPasswordRequestPassword (
1325 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1327 IN UINT16 PortMultiplierPort
,
1328 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1332 CHAR16 PopUpString
[100];
1333 ATA_IDENTIFY_DATA IdentifyData
;
1336 CHAR8 Password
[HDD_PASSWORD_MAX_LENGTH
];
1340 DEBUG ((DEBUG_INFO
, "%a()\n", __FUNCTION__
));
1342 UnicodeSPrint (PopUpString
, sizeof (PopUpString
), L
"Unlock: %s", ConfigFormEntry
->HddString
);
1345 // Check the device security status.
1347 if ((ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
) &&
1348 (ConfigFormEntry
->IfrData
.SecurityStatus
.Enabled
)) {
1351 // Add PcdSkipHddPasswordPrompt to determin whether to skip password prompt.
1352 // Due to board design, device may not power off during system warm boot, which result in
1353 // security status remain unlocked status, hence we add device security status check here.
1355 // If device is in the locked status, device keeps locked and system continues booting.
1356 // If device is in the unlocked status, system is forced shutdown for security concern.
1358 if (PcdGetBool (PcdSkipHddPasswordPrompt
)) {
1359 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1362 gRT
->ResetSystem (EfiResetShutdown
, EFI_SUCCESS
, 0, NULL
);
1366 // As soon as the HDD password is in enabled state, we pop up a window to unlock hdd
1367 // no matter it's really in locked or unlocked state.
1368 // This way forces user to enter password every time to provide best safety.
1371 Status
= PopupHddPasswordInputWindows (PopUpString
, NULL
, Password
);
1372 if (!EFI_ERROR (Status
)) {
1374 // The HDD is in locked state, unlock it by user input.
1376 if (!PasswordIsFullZero (Password
)) {
1377 if (!ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1378 Status
= UnlockHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 0, Password
);
1381 // Use saved HDD password variable to validate HDD password
1382 // when the device is at frozen state.
1384 Status
= ValidateHddPassword (ConfigFormEntry
, Password
);
1387 Status
= EFI_INVALID_PARAMETER
;
1389 if (!EFI_ERROR (Status
)) {
1390 CopyMem (ConfigFormEntry
->Password
, Password
, HDD_PASSWORD_MAX_LENGTH
);
1391 if (!ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1392 SaveHddPasswordVariable (ConfigFormEntry
, Password
);
1394 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1395 Status
= GetHddDeviceIdentifyData (AtaPassThru
, Port
, PortMultiplierPort
, &IdentifyData
);
1396 ASSERT_EFI_ERROR (Status
);
1399 // Check the device security status again.
1401 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
1405 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1407 if (EFI_ERROR (Status
)) {
1409 if (RetryCount
< MAX_HDD_PASSWORD_RETRY_COUNT
) {
1412 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1414 L
"Invalid password.",
1415 L
"Press ENTER to retry",
1418 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1423 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1425 L
"Hdd password retry count is expired. Please shutdown the machine.",
1426 L
"Press ENTER to shutdown",
1429 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1430 gRT
->ResetSystem (EfiResetShutdown
, EFI_SUCCESS
, 0, NULL
);
1434 } else if (Status
== EFI_ABORTED
) {
1435 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1437 // Current device in the lock status and
1438 // User not input password and press ESC,
1439 // keep device in lock status and continue boot.
1443 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1445 L
"Press ENTER to skip the request and continue boot,",
1446 L
"Press ESC to input password again",
1449 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1451 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1452 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1454 // Keep lock and continue boot.
1459 // Let user input password again.
1465 // Current device in the unlock status and
1466 // User not input password and press ESC,
1467 // Shutdown the device.
1471 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1473 L
"Press ENTER to shutdown, Press ESC to input password again",
1476 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1478 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1479 gRT
->ResetSystem (EfiResetShutdown
, EFI_SUCCESS
, 0, NULL
);
1482 // Let user input password again.
1493 Process Set User Pwd HDD password request.
1495 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1496 @param[in] Port The port number of attached ATA device.
1497 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1498 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1502 ProcessHddPasswordRequestSetUserPwd (
1503 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1505 IN UINT16 PortMultiplierPort
,
1506 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1510 CHAR16 PopUpString
[100];
1511 ATA_IDENTIFY_DATA IdentifyData
;
1514 CHAR8 Password
[HDD_PASSWORD_MAX_LENGTH
];
1515 CHAR8 PasswordConfirm
[HDD_PASSWORD_MAX_LENGTH
];
1519 DEBUG ((DEBUG_INFO
, "%a()\n", __FUNCTION__
));
1521 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1522 DEBUG ((DEBUG_INFO
, "%s is frozen, do nothing\n", ConfigFormEntry
->HddString
));
1526 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1527 DEBUG ((DEBUG_INFO
, "%s is locked, do nothing\n", ConfigFormEntry
->HddString
));
1531 UnicodeSPrint (PopUpString
, sizeof (PopUpString
), L
"Set User Pwd: %s", ConfigFormEntry
->HddString
);
1534 // Check the device security status.
1536 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
) {
1538 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please type in your new password", Password
);
1539 if (!EFI_ERROR (Status
)) {
1540 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please confirm your new password", PasswordConfirm
);
1541 if (!EFI_ERROR (Status
)) {
1542 if (CompareMem (Password
, PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
) == 0) {
1543 if (!PasswordIsFullZero (Password
)) {
1544 Status
= SetHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 0, 1, 0, Password
);
1546 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Enabled
) {
1547 Status
= DisableHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 0, ConfigFormEntry
->Password
);
1549 Status
= EFI_INVALID_PARAMETER
;
1552 if (!EFI_ERROR (Status
)) {
1553 CopyMem (ConfigFormEntry
->Password
, Password
, HDD_PASSWORD_MAX_LENGTH
);
1554 SaveHddPasswordVariable (ConfigFormEntry
, Password
);
1555 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1556 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1557 Status
= GetHddDeviceIdentifyData (AtaPassThru
, Port
, PortMultiplierPort
, &IdentifyData
);
1558 ASSERT_EFI_ERROR (Status
);
1561 // Check the device security status again.
1563 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
1568 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1570 L
"Set/Disable User Pwd failed or invalid password.",
1571 L
"Press ENTER to retry",
1574 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1579 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1581 L
"Passwords are not the same.",
1582 L
"Press ENTER to retry",
1585 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1586 Status
= EFI_INVALID_PARAMETER
;
1590 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1591 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1593 if (EFI_ERROR (Status
)) {
1595 if (RetryCount
>= MAX_HDD_PASSWORD_RETRY_COUNT
) {
1598 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1600 L
"Hdd password retry count is expired.",
1601 L
"Press ENTER to skip the request and continue boot",
1604 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1605 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1609 } else if (Status
== EFI_ABORTED
) {
1612 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1614 L
"Press ENTER to skip the request and continue boot,",
1615 L
"Press ESC to input password again",
1618 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1620 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1621 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1625 // Let user input password again.
1635 Process Set Master Pwd HDD password request.
1637 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1638 @param[in] Port The port number of attached ATA device.
1639 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1640 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1644 ProcessHddPasswordRequestSetMasterPwd (
1645 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1647 IN UINT16 PortMultiplierPort
,
1648 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1652 CHAR16 PopUpString
[100];
1655 CHAR8 Password
[HDD_PASSWORD_MAX_LENGTH
];
1656 CHAR8 PasswordConfirm
[HDD_PASSWORD_MAX_LENGTH
];
1660 DEBUG ((DEBUG_INFO
, "%a()\n", __FUNCTION__
));
1662 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Frozen
) {
1663 DEBUG ((DEBUG_INFO
, "%s is frozen, do nothing\n", ConfigFormEntry
->HddString
));
1667 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Locked
) {
1668 DEBUG ((DEBUG_INFO
, "%s is locked, do nothing\n", ConfigFormEntry
->HddString
));
1672 UnicodeSPrint (PopUpString
, sizeof (PopUpString
), L
"Set Master Pwd: %s", ConfigFormEntry
->HddString
);
1675 // Check the device security status.
1677 if (ConfigFormEntry
->IfrData
.SecurityStatus
.Supported
) {
1679 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please type in your new password", Password
);
1680 if (!EFI_ERROR (Status
)) {
1681 Status
= PopupHddPasswordInputWindows (PopUpString
, L
"Please confirm your new password", PasswordConfirm
);
1682 if (!EFI_ERROR (Status
)) {
1683 if (CompareMem (Password
, PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
) == 0) {
1684 if (!PasswordIsFullZero (Password
)) {
1685 Status
= SetHddPassword (AtaPassThru
, Port
, PortMultiplierPort
, 1, 1, 1, Password
);
1687 Status
= EFI_INVALID_PARAMETER
;
1689 if (!EFI_ERROR (Status
)) {
1690 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1691 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1696 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1698 L
"Set Master Pwd failed or invalid password.",
1699 L
"Press ENTER to retry",
1702 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1707 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1709 L
"Passwords are not the same.",
1710 L
"Press ENTER to retry",
1713 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1714 Status
= EFI_INVALID_PARAMETER
;
1718 ZeroMem (Password
, HDD_PASSWORD_MAX_LENGTH
);
1719 ZeroMem (PasswordConfirm
, HDD_PASSWORD_MAX_LENGTH
);
1721 if (EFI_ERROR (Status
)) {
1723 if (RetryCount
>= MAX_HDD_PASSWORD_RETRY_COUNT
) {
1726 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1728 L
"Hdd password retry count is expired.",
1729 L
"Press ENTER to skip the request and continue boot",
1732 } while (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
1733 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1737 } else if (Status
== EFI_ABORTED
) {
1740 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
1742 L
"Press ENTER to skip the request and continue boot,",
1743 L
"Press ESC to input password again",
1746 } while ((Key
.ScanCode
!= SCAN_ESC
) && (Key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
));
1748 if (Key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
1749 gST
->ConOut
->ClearScreen(gST
->ConOut
);
1753 // Let user input password again.
1763 Process HDD password request.
1765 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
1766 @param[in] Port The port number of attached ATA device.
1767 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
1768 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1772 ProcessHddPasswordRequest (
1773 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
1775 IN UINT16 PortMultiplierPort
,
1776 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1780 HDD_PASSWORD_REQUEST_VARIABLE
*TempVariable
;
1781 HDD_PASSWORD_REQUEST_VARIABLE
*Variable
;
1784 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
1786 if (mHddPasswordRequestVariable
== NULL
) {
1787 Status
= GetVariable2 (
1788 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1789 &mHddPasswordVendorGuid
,
1790 (VOID
**) &Variable
,
1793 if (EFI_ERROR (Status
) || (Variable
== NULL
)) {
1796 mHddPasswordRequestVariable
= Variable
;
1797 mHddPasswordRequestVariableSize
= VariableSize
;
1800 // Delete the HDD password request variable.
1802 Status
= gRT
->SetVariable (
1803 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1804 &mHddPasswordVendorGuid
,
1809 ASSERT_EFI_ERROR (Status
);
1811 Variable
= mHddPasswordRequestVariable
;
1812 VariableSize
= mHddPasswordRequestVariableSize
;
1816 // Process the HDD password requests.
1818 TempVariable
= Variable
;
1819 while (VariableSize
>= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
)) {
1820 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
1821 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
1822 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
1823 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
1824 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
)) {
1826 // Found the node for the HDD password device.
1828 if (TempVariable
->Request
.UserPassword
!= 0) {
1829 ProcessHddPasswordRequestSetUserPwd (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
1831 if (TempVariable
->Request
.MasterPassword
!= 0) {
1832 ProcessHddPasswordRequestSetMasterPwd (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
1838 VariableSize
-= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
1842 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
1846 Get saved HDD password request.
1848 @param[in, out] ConfigFormEntry The HDD Password configuration form entry.
1852 GetSavedHddPasswordRequest (
1853 IN OUT HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1857 HDD_PASSWORD_REQUEST_VARIABLE
*TempVariable
;
1858 HDD_PASSWORD_REQUEST_VARIABLE
*Variable
;
1861 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
1866 Status
= GetVariable2 (
1867 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1868 &mHddPasswordVendorGuid
,
1869 (VOID
**) &Variable
,
1872 if (EFI_ERROR (Status
) || (Variable
== NULL
)) {
1876 TempVariable
= Variable
;
1877 while (VariableSize
>= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
)) {
1878 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
1879 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
1880 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
1881 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
1882 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
)) {
1884 // Found the node for the HDD password device.
1885 // Get the HDD password request.
1887 CopyMem (&ConfigFormEntry
->IfrData
.Request
, &TempVariable
->Request
, sizeof (HDD_PASSWORD_REQUEST
));
1890 "HddPasswordRequest got: 0x%x\n",
1891 ConfigFormEntry
->IfrData
.Request
1895 VariableSize
-= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
1899 FreePool (Variable
);
1901 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
1905 Save HDD password request.
1907 @param[in] ConfigFormEntry The HDD Password configuration form entry.
1911 SaveHddPasswordRequest (
1912 IN HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
1916 HDD_PASSWORD_REQUEST_VARIABLE
*TempVariable
;
1917 UINTN TempVariableSize
;
1918 HDD_PASSWORD_REQUEST_VARIABLE
*Variable
;
1920 HDD_PASSWORD_REQUEST_VARIABLE
*NewVariable
;
1921 UINTN NewVariableSize
;
1923 DEBUG ((DEBUG_INFO
, "%a() - enter\n", __FUNCTION__
));
1927 "HddPasswordRequest to save: 0x%x\n",
1928 ConfigFormEntry
->IfrData
.Request
1934 NewVariableSize
= 0;
1936 Status
= GetVariable2 (
1937 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1938 &mHddPasswordVendorGuid
,
1939 (VOID
**) &Variable
,
1942 if (!EFI_ERROR (Status
) && (Variable
!= NULL
)) {
1943 TempVariable
= Variable
;
1944 TempVariableSize
= VariableSize
;
1945 while (TempVariableSize
>= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
)) {
1946 if ((TempVariable
->Device
.Bus
== ConfigFormEntry
->Bus
) &&
1947 (TempVariable
->Device
.Device
== ConfigFormEntry
->Device
) &&
1948 (TempVariable
->Device
.Function
== ConfigFormEntry
->Function
) &&
1949 (TempVariable
->Device
.Port
== ConfigFormEntry
->Port
) &&
1950 (TempVariable
->Device
.PortMultiplierPort
== ConfigFormEntry
->PortMultiplierPort
)) {
1952 // Found the node for the HDD password device.
1953 // Update the HDD password request.
1955 CopyMem (&TempVariable
->Request
, &ConfigFormEntry
->IfrData
.Request
, sizeof (HDD_PASSWORD_REQUEST
));
1956 NewVariable
= Variable
;
1957 NewVariableSize
= VariableSize
;
1960 TempVariableSize
-= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
1963 if (NewVariable
== NULL
) {
1965 // The node for the HDD password device is not found.
1966 // Create node for the HDD password device.
1968 NewVariableSize
= VariableSize
+ sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
1969 NewVariable
= AllocateZeroPool (NewVariableSize
);
1970 ASSERT (NewVariable
!= NULL
);
1971 CopyMem (NewVariable
, Variable
, VariableSize
);
1972 TempVariable
= (HDD_PASSWORD_REQUEST_VARIABLE
*) ((UINTN
) NewVariable
+ VariableSize
);
1973 TempVariable
->Device
.Bus
= (UINT8
) ConfigFormEntry
->Bus
;
1974 TempVariable
->Device
.Device
= (UINT8
) ConfigFormEntry
->Device
;
1975 TempVariable
->Device
.Function
= (UINT8
) ConfigFormEntry
->Function
;
1976 TempVariable
->Device
.Port
= ConfigFormEntry
->Port
;
1977 TempVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
1978 CopyMem (&TempVariable
->Request
, &ConfigFormEntry
->IfrData
.Request
, sizeof (HDD_PASSWORD_REQUEST
));
1981 NewVariableSize
= sizeof (HDD_PASSWORD_REQUEST_VARIABLE
);
1982 NewVariable
= AllocateZeroPool (NewVariableSize
);
1983 ASSERT (NewVariable
!= NULL
);
1984 NewVariable
->Device
.Bus
= (UINT8
) ConfigFormEntry
->Bus
;
1985 NewVariable
->Device
.Device
= (UINT8
) ConfigFormEntry
->Device
;
1986 NewVariable
->Device
.Function
= (UINT8
) ConfigFormEntry
->Function
;
1987 NewVariable
->Device
.Port
= ConfigFormEntry
->Port
;
1988 NewVariable
->Device
.PortMultiplierPort
= ConfigFormEntry
->PortMultiplierPort
;
1989 CopyMem (&NewVariable
->Request
, &ConfigFormEntry
->IfrData
.Request
, sizeof (HDD_PASSWORD_REQUEST
));
1991 Status
= gRT
->SetVariable (
1992 HDD_PASSWORD_REQUEST_VARIABLE_NAME
,
1993 &mHddPasswordVendorGuid
,
1994 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1998 if (EFI_ERROR (Status
)) {
1999 DEBUG ((DEBUG_INFO
, "HddPasswordRequest variable set failed (%r)\n", Status
));
2001 if (NewVariable
!= Variable
) {
2002 FreePool (NewVariable
);
2004 if (Variable
!= NULL
) {
2005 FreePool (Variable
);
2008 DEBUG ((DEBUG_INFO
, "%a() - exit\n", __FUNCTION__
));
2012 Get the HDD Password configuration form entry by the index of the goto opcode activated.
2014 @param[in] Index The 0-based index of the goto opcode activated.
2016 @return The HDD Password configuration form entry found.
2018 HDD_PASSWORD_CONFIG_FORM_ENTRY
*
2019 HddPasswordGetConfigFormEntryByIndex (
2024 UINT32 CurrentIndex
;
2025 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
2028 ConfigFormEntry
= NULL
;
2030 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
2031 if (CurrentIndex
== Index
) {
2032 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
2039 return ConfigFormEntry
;
2043 This function allows the caller to request the current
2044 configuration for one or more named elements. The resulting
2045 string is in <ConfigAltResp> format. Any and all alternative
2046 configuration strings shall also be appended to the end of the
2047 current configuration string. If they are, they must appear
2048 after the current configuration. They must contain the same
2049 routing (GUID, NAME, PATH) as the current configuration string.
2050 They must have an additional description indicating the type of
2051 alternative configuration the string represents,
2052 "ALTCFG=<StringToken>". That <StringToken> (when
2053 converted from Hex UNICODE to binary) is a reference to a
2054 string in the associated string pack.
2056 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2057 @param[in] Request A null-terminated Unicode string in
2058 <ConfigRequest> format. Note that this
2059 includes the routing information as well as
2060 the configurable name / value pairs. It is
2061 invalid for this string to be in
2062 <MultiConfigRequest> format.
2063 @param[out] Progress On return, points to a character in the
2064 Request string. Points to the string's null
2065 terminator if request was successful. Points
2066 to the most recent "&" before the first
2067 failing name / value pair (or the beginning
2068 of the string if the failure is in the first
2069 name / value pair) if the request was not
2071 @param[out] Results A null-terminated Unicode string in
2072 <ConfigAltResp> format which has all values
2073 filled in for the names in the Request string.
2074 String to be allocated by the called function.
2076 @retval EFI_SUCCESS The Results string is filled with the
2077 values corresponding to all requested
2079 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2080 parts of the results that must be
2081 stored awaiting possible future
2083 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
2084 for the Request parameter
2085 would result in this type of
2086 error. In this case, the
2087 Progress parameter would be
2089 @retval EFI_NOT_FOUND Routing data doesn't match any
2090 known driver. Progress set to the
2091 first character in the routing header.
2092 Note: There is no requirement that the
2093 driver validate the routing data. It
2094 must skip the <ConfigHdr> in order to
2096 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
2097 to most recent & before the
2098 error or the beginning of the
2100 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
2101 to the & before the name in
2102 question.Currently not implemented.
2106 HddPasswordFormExtractConfig (
2107 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2108 IN CONST EFI_STRING Request
,
2109 OUT EFI_STRING
*Progress
,
2110 OUT EFI_STRING
*Results
2115 HDD_PASSWORD_CONFIG
*IfrData
;
2116 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2117 EFI_STRING ConfigRequestHdr
;
2118 EFI_STRING ConfigRequest
;
2119 BOOLEAN AllocatedRequest
;
2122 if (Progress
== NULL
|| Results
== NULL
) {
2123 return EFI_INVALID_PARAMETER
;
2126 *Progress
= Request
;
2127 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
)) {
2128 return EFI_NOT_FOUND
;
2131 ConfigRequestHdr
= NULL
;
2132 ConfigRequest
= NULL
;
2133 AllocatedRequest
= FALSE
;
2136 Private
= HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This
);
2137 IfrData
= AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG
));
2138 ASSERT (IfrData
!= NULL
);
2139 if (Private
->Current
!= NULL
) {
2140 CopyMem (IfrData
, &Private
->Current
->IfrData
, sizeof (HDD_PASSWORD_CONFIG
));
2144 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
2146 BufferSize
= sizeof (HDD_PASSWORD_CONFIG
);
2147 ConfigRequest
= Request
;
2148 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2150 // Request has no request element, construct full request string.
2151 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2152 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2154 ConfigRequestHdr
= HiiConstructConfigHdr (&mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
, Private
->DriverHandle
);
2155 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2156 ConfigRequest
= AllocateZeroPool (Size
);
2157 ASSERT (ConfigRequest
!= NULL
);
2158 AllocatedRequest
= TRUE
;
2159 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2160 FreePool (ConfigRequestHdr
);
2162 Status
= gHiiConfigRouting
->BlockToConfig (
2172 // Free the allocated config request string.
2174 if (AllocatedRequest
) {
2175 FreePool (ConfigRequest
);
2176 ConfigRequest
= NULL
;
2180 // Set Progress string to the original request string.
2182 if (Request
== NULL
) {
2184 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2185 *Progress
= Request
+ StrLen (Request
);
2192 This function applies changes in a driver's configuration.
2193 Input is a Configuration, which has the routing data for this
2194 driver followed by name / value configuration pairs. The driver
2195 must apply those pairs to its configurable storage. If the
2196 driver's configuration is stored in a linear block of data
2197 and the driver's name / value pairs are in <BlockConfig>
2198 format, it may use the ConfigToBlock helper function (above) to
2199 simplify the job. Currently not implemented.
2201 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2202 @param[in] Configuration A null-terminated Unicode string in
2203 <ConfigString> format.
2204 @param[out] Progress A pointer to a string filled in with the
2205 offset of the most recent '&' before the
2206 first failing name / value pair (or the
2207 beginn ing of the string if the failure
2208 is in the first name / value pair) or
2209 the terminating NULL if all was
2212 @retval EFI_SUCCESS The results have been distributed or are
2213 awaiting distribution.
2214 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
2215 parts of the results that must be
2216 stored awaiting possible future
2218 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
2219 Results parameter would result
2220 in this type of error.
2221 @retval EFI_NOT_FOUND Target for the specified routing data
2226 HddPasswordFormRouteConfig (
2227 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2228 IN CONST EFI_STRING Configuration
,
2229 OUT EFI_STRING
*Progress
2232 if (Configuration
== NULL
|| Progress
== NULL
) {
2233 return EFI_INVALID_PARAMETER
;
2237 // Check routing data in <ConfigHdr>.
2238 // Note: if only one Storage is used, then this checking could be skipped.
2240 if (!HiiIsConfigHdrMatch (Configuration
, &mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
)) {
2241 *Progress
= Configuration
;
2242 return EFI_NOT_FOUND
;
2245 *Progress
= Configuration
+ StrLen (Configuration
);
2250 This function is called to provide results data to the driver.
2251 This data consists of a unique key that is used to identify
2252 which data is either being passed back or being asked for.
2254 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2255 @param[in] Action Specifies the type of action taken by the browser.
2256 @param[in] QuestionId A unique value which is sent to the original
2257 exporting driver so that it can identify the type
2258 of data to expect. The format of the data tends to
2259 vary based on the opcode that enerated the callback.
2260 @param[in] Type The type of value for the question.
2261 @param[in] Value A pointer to the data being sent to the original
2263 @param[out] ActionRequest On return, points to the action requested by the
2266 @retval EFI_SUCCESS The callback successfully handled the action.
2267 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2268 variable and its data.
2269 @retval EFI_DEVICE_ERROR The variable could not be saved.
2270 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2271 callback.Currently not implemented.
2272 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
2273 @retval Others Other errors as indicated.
2277 HddPasswordFormCallback (
2278 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2279 IN EFI_BROWSER_ACTION Action
,
2280 IN EFI_QUESTION_ID QuestionId
,
2282 IN EFI_IFR_TYPE_VALUE
*Value
,
2283 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2286 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2287 EFI_STRING_ID DeviceFormTitleToken
;
2288 HDD_PASSWORD_CONFIG
*IfrData
;
2289 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
2291 if (ActionRequest
!= NULL
) {
2292 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_NONE
;
2294 return EFI_INVALID_PARAMETER
;
2297 if ((Action
!= EFI_BROWSER_ACTION_CHANGING
) && (Action
!= EFI_BROWSER_ACTION_CHANGED
)) {
2299 // Do nothing for other UEFI Action. Only do call back when data is changing or changed.
2301 return EFI_UNSUPPORTED
;
2304 Private
= HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This
);
2307 // Retrive data from Browser
2309 IfrData
= AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG
));
2310 ASSERT (IfrData
!= NULL
);
2311 if (!HiiGetBrowserData (&mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
, sizeof (HDD_PASSWORD_CONFIG
), (UINT8
*) IfrData
)) {
2313 return EFI_NOT_FOUND
;
2316 switch (QuestionId
) {
2317 case KEY_HDD_USER_PASSWORD
:
2318 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2319 DEBUG ((DEBUG_INFO
, "KEY_HDD_USER_PASSWORD\n"));
2320 ConfigFormEntry
= Private
->Current
;
2321 ConfigFormEntry
->IfrData
.Request
.UserPassword
= Value
->b
;
2322 SaveHddPasswordRequest (ConfigFormEntry
);
2323 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2326 case KEY_HDD_MASTER_PASSWORD
:
2327 if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2328 DEBUG ((DEBUG_INFO
, "KEY_HDD_MASTER_PASSWORD\n"));
2329 ConfigFormEntry
= Private
->Current
;
2330 ConfigFormEntry
->IfrData
.Request
.MasterPassword
= Value
->b
;
2331 SaveHddPasswordRequest (ConfigFormEntry
);
2332 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2337 if ((QuestionId
>= KEY_HDD_DEVICE_ENTRY_BASE
) && (QuestionId
< (mNumberOfHddDevices
+ KEY_HDD_DEVICE_ENTRY_BASE
))) {
2338 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2340 // In case goto the device configuration form, update the device form title.
2342 ConfigFormEntry
= HddPasswordGetConfigFormEntryByIndex ((UINT32
) (QuestionId
- KEY_HDD_DEVICE_ENTRY_BASE
));
2343 ASSERT (ConfigFormEntry
!= NULL
);
2345 DeviceFormTitleToken
= (EFI_STRING_ID
) STR_HDD_SECURITY_HD
;
2346 HiiSetString (Private
->HiiHandle
, DeviceFormTitleToken
, ConfigFormEntry
->HddString
, NULL
);
2348 Private
->Current
= ConfigFormEntry
;
2349 CopyMem (IfrData
, &ConfigFormEntry
->IfrData
, sizeof (HDD_PASSWORD_CONFIG
));
2357 // Pass changed uncommitted data back to Form Browser
2359 HiiSetBrowserData (&mHddPasswordVendorGuid
, mHddPasswordVendorStorageName
, sizeof (HDD_PASSWORD_CONFIG
), (UINT8
*) IfrData
, NULL
);
2366 Updates the HDD Password configuration form to add an entry for the attached
2367 ata harddisk device specified by the Controller.
2369 @param[in] HiiHandle The HII Handle associated with the registered package list.
2370 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
2371 @param[in] PciIo Pointer to PCI_IO instance.
2372 @param[in] Controller The controller handle of the attached ata controller.
2373 @param[in] Bus The bus number of ATA controller.
2374 @param[in] Device The device number of ATA controller.
2375 @param[in] Function The function number of ATA controller.
2376 @param[in] Port The port number of attached ATA device.
2377 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
2379 @retval EFI_SUCCESS The Hdd Password configuration form is updated.
2380 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2381 @retval Others Other errors as indicated.
2385 HddPasswordConfigUpdateForm (
2386 IN EFI_HII_HANDLE HiiHandle
,
2387 IN EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
,
2388 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2389 IN EFI_HANDLE Controller
,
2394 IN UINT16 PortMultiplierPort
2398 HDD_PASSWORD_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
2399 BOOLEAN EntryExisted
;
2401 VOID
*StartOpCodeHandle
;
2402 VOID
*EndOpCodeHandle
;
2403 EFI_IFR_GUID_LABEL
*StartLabel
;
2404 EFI_IFR_GUID_LABEL
*EndLabel
;
2405 CHAR16 HddString
[40];
2406 ATA_IDENTIFY_DATA IdentifyData
;
2407 EFI_DEVICE_PATH_PROTOCOL
*AtaDeviceNode
;
2409 ConfigFormEntry
= NULL
;
2410 EntryExisted
= FALSE
;
2412 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
2413 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
2415 if ((ConfigFormEntry
->Bus
== Bus
) &&
2416 (ConfigFormEntry
->Device
== Device
) &&
2417 (ConfigFormEntry
->Function
== Function
) &&
2418 (ConfigFormEntry
->Port
== Port
) &&
2419 (ConfigFormEntry
->PortMultiplierPort
== PortMultiplierPort
)) {
2420 EntryExisted
= TRUE
;
2425 if (!EntryExisted
) {
2429 ConfigFormEntry
= AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG_FORM_ENTRY
));
2430 if (ConfigFormEntry
== NULL
) {
2431 return EFI_OUT_OF_RESOURCES
;
2434 InitializeListHead (&ConfigFormEntry
->Link
);
2435 ConfigFormEntry
->Controller
= Controller
;
2436 ConfigFormEntry
->Bus
= Bus
;
2437 ConfigFormEntry
->Device
= Device
;
2438 ConfigFormEntry
->Function
= Function
;
2439 ConfigFormEntry
->Port
= Port
;
2440 ConfigFormEntry
->PortMultiplierPort
= PortMultiplierPort
;
2441 ConfigFormEntry
->AtaPassThru
= AtaPassThru
;
2443 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
));
2446 // Construct the device path for the HDD password device
2448 Status
= AtaPassThru
->BuildDevicePath (
2454 if (EFI_ERROR (Status
)) {
2457 ConfigFormEntry
->DevicePath
= AppendDevicePathNode (DevicePathFromHandle (Controller
), AtaDeviceNode
);
2458 FreePool (AtaDeviceNode
);
2459 if (ConfigFormEntry
->DevicePath
== NULL
) {
2460 return EFI_OUT_OF_RESOURCES
;
2464 // Get attached harddisk model number
2466 Status
= GetHddDeviceIdentifyData (AtaPassThru
, Port
, PortMultiplierPort
, &IdentifyData
);
2467 ASSERT_EFI_ERROR (Status
);
2468 if (EFI_ERROR (Status
)) {
2471 GetHddDeviceModelNumber (&IdentifyData
, HddString
);
2473 // Compose the HDD title string and help string of this port and create a new EFI_STRING_ID.
2475 UnicodeSPrint (ConfigFormEntry
->HddString
, sizeof (ConfigFormEntry
->HddString
), L
"HDD %d:%s", mNumberOfHddDevices
, HddString
);
2476 ConfigFormEntry
->TitleToken
= HiiSetString (HiiHandle
, 0, ConfigFormEntry
->HddString
, NULL
);
2477 ConfigFormEntry
->TitleHelpToken
= HiiSetString (HiiHandle
, 0, L
"Request to set HDD Password", NULL
);
2479 GetHddPasswordSecurityStatus (&IdentifyData
, &ConfigFormEntry
->IfrData
);
2481 InsertTailList (&mHddPasswordConfigFormList
, &ConfigFormEntry
->Link
);
2484 // Init OpCode Handle
2486 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2487 ASSERT (StartOpCodeHandle
!= NULL
);
2489 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2490 ASSERT (EndOpCodeHandle
!= NULL
);
2493 // Create Hii Extend Label OpCode as the start opcode
2495 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
2496 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2497 StartLabel
->Number
= HDD_DEVICE_ENTRY_LABEL
;
2500 // Create Hii Extend Label OpCode as the end opcode
2502 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
2503 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2504 EndLabel
->Number
= HDD_DEVICE_LABEL_END
;
2506 mNumberOfHddDevices
= 0;
2507 BASE_LIST_FOR_EACH (Entry
, &mHddPasswordConfigFormList
) {
2508 ConfigFormEntry
= BASE_CR (Entry
, HDD_PASSWORD_CONFIG_FORM_ENTRY
, Link
);
2510 HiiCreateGotoOpCode (
2511 StartOpCodeHandle
, // Container for dynamic created opcodes
2512 FORMID_HDD_DEVICE_FORM
, // Target Form ID
2513 ConfigFormEntry
->TitleToken
, // Prompt text
2514 ConfigFormEntry
->TitleHelpToken
, // Help text
2515 EFI_IFR_FLAG_CALLBACK
, // Question flag
2516 (UINT16
) (KEY_HDD_DEVICE_ENTRY_BASE
+ mNumberOfHddDevices
) // Question ID
2519 mNumberOfHddDevices
++;
2524 &mHddPasswordVendorGuid
,
2525 FORMID_HDD_MAIN_FORM
,
2530 HiiFreeOpCodeHandle (StartOpCodeHandle
);
2531 HiiFreeOpCodeHandle (EndOpCodeHandle
);
2534 // Check if device is locked and prompt for password.
2536 HddPasswordRequestPassword (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
2539 // Process HDD password request from last boot.
2541 ProcessHddPasswordRequest (AtaPassThru
, Port
, PortMultiplierPort
, ConfigFormEntry
);
2548 Ata Pass Thru Protocol notification event handler.
2550 Check attached harddisk status to see if it's locked. If yes, then pop up a password windows to require user input.
2551 It also registers a form for user configuration on Hdd password configuration.
2553 @param[in] Event Event whose notification function is being invoked.
2554 @param[in] Context Pointer to the notification function's context.
2559 HddPasswordNotificationEvent (
2565 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2566 EFI_ATA_PASS_THRU_PROTOCOL
*AtaPassThru
;
2568 UINT16 PortMultiplierPort
;
2569 EFI_HANDLE Controller
;
2570 EFI_HANDLE
*HandleBuffer
;
2573 EFI_PCI_IO_PROTOCOL
*PciIo
;
2579 if (mHddPasswordEndOfDxe
) {
2580 gBS
->CloseEvent (Event
);
2584 Private
= (HDD_PASSWORD_DXE_PRIVATE_DATA
*)Context
;
2587 // Locate all handles of AtaPassThru protocol
2589 Status
= gBS
->LocateHandleBuffer (
2591 &gEfiAtaPassThruProtocolGuid
,
2596 if (EFI_ERROR (Status
)) {
2601 // Check attached hard disk status to see if it's locked
2603 for (Index
= 0; Index
< HandleCount
; Index
+= 1) {
2604 Controller
= HandleBuffer
[Index
];
2605 Status
= gBS
->HandleProtocol (
2607 &gEfiAtaPassThruProtocolGuid
,
2608 (VOID
**) &AtaPassThru
2610 if (EFI_ERROR (Status
)) {
2615 // Ignore those logical ATA_PASS_THRU instance.
2617 if ((AtaPassThru
->Mode
->Attributes
& EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL
) == 0) {
2621 Status
= gBS
->HandleProtocol (
2623 &gEfiPciIoProtocolGuid
,
2626 ASSERT_EFI_ERROR (Status
);
2627 if (EFI_ERROR (Status
)) {
2631 Status
= PciIo
->GetLocation (
2638 ASSERT_EFI_ERROR (Status
);
2639 if (EFI_ERROR (Status
)) {
2644 // Assume and only support Segment == 0.
2646 ASSERT (SegNum
== 0);
2649 // traverse all attached harddisk devices to update form and unlock it
2654 Status
= AtaPassThru
->GetNextPort (AtaPassThru
, &Port
);
2655 if (EFI_ERROR (Status
)) {
2657 // We cannot find more legal port then we are done.
2662 PortMultiplierPort
= 0xFFFF;
2664 Status
= AtaPassThru
->GetNextDevice (AtaPassThru
, Port
, &PortMultiplierPort
);
2665 if (EFI_ERROR (Status
)) {
2667 // We cannot find more legal port multiplier port number for ATA device
2668 // on the port, then we are done.
2673 // Find out the attached harddisk devices.
2674 // Try to add a HDD Password configuration page for the attached devices.
2676 gBS
->RestoreTPL (TPL_APPLICATION
);
2677 Status
= HddPasswordConfigUpdateForm (Private
->HiiHandle
, AtaPassThru
, PciIo
, Controller
, BusNum
, DevNum
, FuncNum
, Port
, PortMultiplierPort
);
2678 gBS
->RaiseTPL (TPL_CALLBACK
);
2679 if (EFI_ERROR (Status
)) {
2686 FreePool (HandleBuffer
);
2691 Initialize the HDD Password configuration form.
2693 @param[out] Instance Pointer to private instance.
2695 @retval EFI_SUCCESS The HDD Password configuration form is initialized.
2696 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2697 @retval Others Other errors as indicated.
2700 HddPasswordConfigFormInit (
2701 OUT HDD_PASSWORD_DXE_PRIVATE_DATA
**Instance
2705 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2707 InitializeListHead (&mHddPasswordConfigFormList
);
2709 Private
= AllocateZeroPool (sizeof (HDD_PASSWORD_DXE_PRIVATE_DATA
));
2710 if (Private
== NULL
) {
2711 return EFI_OUT_OF_RESOURCES
;
2714 Private
->Signature
= HDD_PASSWORD_DXE_PRIVATE_SIGNATURE
;
2716 Private
->ConfigAccess
.ExtractConfig
= HddPasswordFormExtractConfig
;
2717 Private
->ConfigAccess
.RouteConfig
= HddPasswordFormRouteConfig
;
2718 Private
->ConfigAccess
.Callback
= HddPasswordFormCallback
;
2721 // Install Device Path Protocol and Config Access protocol to driver handle
2723 Status
= gBS
->InstallMultipleProtocolInterfaces (
2724 &Private
->DriverHandle
,
2725 &gEfiDevicePathProtocolGuid
,
2726 &mHddPasswordHiiVendorDevicePath
,
2727 &gEfiHiiConfigAccessProtocolGuid
,
2728 &Private
->ConfigAccess
,
2731 ASSERT_EFI_ERROR (Status
);
2732 if (EFI_ERROR (Status
)) {
2738 // Publish our HII data
2740 Private
->HiiHandle
= HiiAddPackages (
2741 &mHddPasswordVendorGuid
,
2742 Private
->DriverHandle
,
2743 HddPasswordDxeStrings
,
2747 if (Private
->HiiHandle
== NULL
) {
2749 return EFI_OUT_OF_RESOURCES
;
2752 *Instance
= Private
;
2757 Main entry for this driver.
2759 @param ImageHandle Image handle this driver.
2760 @param SystemTable Pointer to SystemTable.
2762 @retval EFI_SUCCESS This function always complete successfully.
2767 HddPasswordDxeInit (
2768 IN EFI_HANDLE ImageHandle
,
2769 IN EFI_SYSTEM_TABLE
*SystemTable
2773 HDD_PASSWORD_DXE_PRIVATE_DATA
*Private
;
2775 EFI_EVENT EndOfDxeEvent
;
2776 EDKII_VARIABLE_LOCK_PROTOCOL
*VariableLock
;
2781 // Initialize the configuration form of HDD Password.
2783 Status
= HddPasswordConfigFormInit (&Private
);
2784 if (EFI_ERROR (Status
)) {
2789 // Register HddPasswordNotificationEvent() notify function.
2791 EfiCreateProtocolNotifyEvent (
2792 &gEfiAtaPassThruProtocolGuid
,
2794 HddPasswordNotificationEvent
,
2799 Status
= gBS
->CreateEventEx (
2802 HddPasswordEndOfDxeEventNotify
,
2804 &gEfiEndOfDxeEventGroupGuid
,
2807 ASSERT_EFI_ERROR (Status
);
2810 // Make HDD_PASSWORD_VARIABLE_NAME variable read-only.
2812 Status
= gBS
->LocateProtocol (&gEdkiiVariableLockProtocolGuid
, NULL
, (VOID
**) &VariableLock
);
2813 if (!EFI_ERROR (Status
)) {
2814 Status
= VariableLock
->RequestToLock (
2816 HDD_PASSWORD_VARIABLE_NAME
,
2817 &mHddPasswordVendorGuid
2819 DEBUG ((DEBUG_INFO
, "%a(): Lock %s variable (%r)\n", __FUNCTION__
, HDD_PASSWORD_VARIABLE_NAME
, Status
));
2820 ASSERT_EFI_ERROR (Status
);