]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/HddPassword/HddPasswordDxe.c
UefiCpuPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / SecurityPkg / HddPassword / HddPasswordDxe.c
CommitLineData
e8959f81
HW
1/** @file\r
2 HDD password driver which is used to support HDD security feature.\r
3\r
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
3571e136 5 Copyright (c) Microsoft Corporation.<BR>\r
e8959f81 6\r
289b714b 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e8959f81
HW
8\r
9**/\r
10\r
11#include "HddPasswordDxe.h"\r
12\r
13EFI_GUID mHddPasswordVendorGuid = HDD_PASSWORD_CONFIG_GUID;\r
14CHAR16 mHddPasswordVendorStorageName[] = L"HDD_PASSWORD_CONFIG";\r
15LIST_ENTRY mHddPasswordConfigFormList;\r
16UINT32 mNumberOfHddDevices = 0;\r
17\r
18EFI_GUID mHddPasswordDeviceInfoGuid = HDD_PASSWORD_DEVICE_INFO_GUID;\r
19BOOLEAN mHddPasswordEndOfDxe = FALSE;\r
20HDD_PASSWORD_REQUEST_VARIABLE *mHddPasswordRequestVariable = NULL;\r
21UINTN mHddPasswordRequestVariableSize = 0;\r
22\r
23HII_VENDOR_DEVICE_PATH mHddPasswordHiiVendorDevicePath = {\r
24 {\r
25 {\r
26 HARDWARE_DEVICE_PATH,\r
27 HW_VENDOR_DP,\r
28 {\r
29 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
30 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
31 }\r
32 },\r
33 HDD_PASSWORD_CONFIG_GUID\r
34 },\r
35 {\r
36 END_DEVICE_PATH_TYPE,\r
37 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
38 {\r
39 (UINT8) (END_DEVICE_PATH_LENGTH),\r
40 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
41 }\r
42 }\r
43};\r
44\r
45\r
46/**\r
47 Check if the password is full zero.\r
48\r
49 @param[in] Password Points to the data buffer\r
50\r
51 @retval TRUE This password string is full zero.\r
52 @retval FALSE This password string is not full zero.\r
53\r
54**/\r
55BOOLEAN\r
56PasswordIsFullZero (\r
57 IN CHAR8 *Password\r
58 )\r
59{\r
60 UINTN Index;\r
61\r
62 for (Index = 0; Index < HDD_PASSWORD_MAX_LENGTH; Index++) {\r
63 if (Password[Index] != 0) {\r
64 return FALSE;\r
65 }\r
66 }\r
67\r
68 return TRUE;\r
69}\r
70\r
71/**\r
72 Save device info.\r
73\r
74 @param[in] ConfigFormEntry Points to HDD_PASSWORD_CONFIG_FORM_ENTRY buffer\r
75 @param[in,out] TempDevInfo Points to HDD_PASSWORD_DEVICE_INFO buffer\r
76\r
77**/\r
78VOID\r
79SaveDeviceInfo (\r
80 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
81 IN OUT HDD_PASSWORD_DEVICE_INFO *TempDevInfo\r
82 )\r
83{\r
84 TempDevInfo->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
85 TempDevInfo->Device.Device = (UINT8) ConfigFormEntry->Device;\r
86 TempDevInfo->Device.Function = (UINT8) ConfigFormEntry->Function;\r
87 TempDevInfo->Device.Port = ConfigFormEntry->Port;\r
88 TempDevInfo->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
89 CopyMem (TempDevInfo->Password, ConfigFormEntry->Password, HDD_PASSWORD_MAX_LENGTH);\r
90 TempDevInfo->DevicePathLength = (UINT32) GetDevicePathSize (ConfigFormEntry->DevicePath);\r
91 CopyMem (TempDevInfo->DevicePath, ConfigFormEntry->DevicePath, TempDevInfo->DevicePathLength);\r
92}\r
93\r
94/**\r
95 Build HDD password device info and save them to LockBox.\r
96\r
97 **/\r
98VOID\r
99BuildHddPasswordDeviceInfo (\r
100 VOID\r
101 )\r
102{\r
103 EFI_STATUS Status;\r
104 LIST_ENTRY *Entry;\r
105 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
106 HDD_PASSWORD_DEVICE_INFO *DevInfo;\r
107 HDD_PASSWORD_DEVICE_INFO *TempDevInfo;\r
108 UINTN DevInfoLength;\r
109 UINT8 DummyData;\r
110 BOOLEAN S3InitDevicesExist;\r
111 UINTN S3InitDevicesLength;\r
112 EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;\r
113 EFI_DEVICE_PATH_PROTOCOL *S3InitDevicesBak;\r
114\r
115 //\r
116 // Build HDD password device info and save them to LockBox.\r
117 //\r
118 DevInfoLength = 0;\r
3571e136 119 BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
e8959f81
HW
120 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
121\r
122 //\r
123 // 1. Handle device which already set password.\r
d6b926e7 124 // 2. When request to send freeze command, driver also needs to handle device\r
e8959f81
HW
125 // which support security feature.\r
126 //\r
127 if ((!PasswordIsFullZero (ConfigFormEntry->Password)) ||\r
128 ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&\r
129 (ConfigFormEntry->IfrData.SecurityStatus.Enabled == 0))) {\r
130 DevInfoLength += sizeof (HDD_PASSWORD_DEVICE_INFO) +\r
131 GetDevicePathSize (ConfigFormEntry->DevicePath);\r
132 }\r
133 }\r
134\r
135 if (DevInfoLength == 0) {\r
136 return;\r
137 }\r
138\r
139 S3InitDevicesLength = sizeof (DummyData);\r
140 Status = RestoreLockBox (\r
141 &gS3StorageDeviceInitListGuid,\r
142 &DummyData,\r
143 &S3InitDevicesLength\r
144 );\r
145 ASSERT ((Status == EFI_NOT_FOUND) || (Status == EFI_BUFFER_TOO_SMALL));\r
146 if (Status == EFI_NOT_FOUND) {\r
147 S3InitDevices = NULL;\r
148 S3InitDevicesExist = FALSE;\r
149 } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
150 S3InitDevices = AllocatePool (S3InitDevicesLength);\r
151 ASSERT (S3InitDevices != NULL);\r
152\r
153 Status = RestoreLockBox (\r
154 &gS3StorageDeviceInitListGuid,\r
155 S3InitDevices,\r
156 &S3InitDevicesLength\r
157 );\r
158 ASSERT_EFI_ERROR (Status);\r
159 S3InitDevicesExist = TRUE;\r
160 } else {\r
161 return;\r
162 }\r
163\r
164 DevInfo = AllocateZeroPool (DevInfoLength);\r
165 ASSERT (DevInfo != NULL);\r
166\r
167 TempDevInfo = DevInfo;\r
3571e136 168 BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
e8959f81
HW
169 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
170\r
171 if ((!PasswordIsFullZero (ConfigFormEntry->Password)) ||\r
172 ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&\r
173 (ConfigFormEntry->IfrData.SecurityStatus.Enabled == 0))) {\r
174 SaveDeviceInfo (ConfigFormEntry, TempDevInfo);\r
175\r
176 S3InitDevicesBak = S3InitDevices;\r
177 S3InitDevices = AppendDevicePathInstance (\r
178 S3InitDevicesBak,\r
179 ConfigFormEntry->DevicePath\r
180 );\r
181 if (S3InitDevicesBak != NULL) {\r
182 FreePool (S3InitDevicesBak);\r
183 }\r
184 ASSERT (S3InitDevices != NULL);\r
185\r
186 TempDevInfo = (HDD_PASSWORD_DEVICE_INFO *) ((UINTN)TempDevInfo +\r
187 sizeof (HDD_PASSWORD_DEVICE_INFO) +\r
188 TempDevInfo->DevicePathLength);\r
189 }\r
190 }\r
191\r
192 Status = SaveLockBox (\r
193 &mHddPasswordDeviceInfoGuid,\r
194 DevInfo,\r
195 DevInfoLength\r
196 );\r
197 ASSERT_EFI_ERROR (Status);\r
198\r
199 Status = SetLockBoxAttributes (\r
200 &mHddPasswordDeviceInfoGuid,\r
201 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
202 );\r
203 ASSERT_EFI_ERROR (Status);\r
204\r
205 S3InitDevicesLength = GetDevicePathSize (S3InitDevices);\r
206 if (S3InitDevicesExist) {\r
207 Status = UpdateLockBox (\r
208 &gS3StorageDeviceInitListGuid,\r
209 0,\r
210 S3InitDevices,\r
211 S3InitDevicesLength\r
212 );\r
213 ASSERT_EFI_ERROR (Status);\r
214 } else {\r
215 Status = SaveLockBox (\r
216 &gS3StorageDeviceInitListGuid,\r
217 S3InitDevices,\r
218 S3InitDevicesLength\r
219 );\r
220 ASSERT_EFI_ERROR (Status);\r
221\r
222 Status = SetLockBoxAttributes (\r
223 &gS3StorageDeviceInitListGuid,\r
224 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
225 );\r
226 ASSERT_EFI_ERROR (Status);\r
227 }\r
228\r
229 ZeroMem (DevInfo, DevInfoLength);\r
230 FreePool (DevInfo);\r
231 FreePool (S3InitDevices);\r
232}\r
233\r
234/**\r
235 Send freeze lock cmd through Ata Pass Thru Protocol.\r
236\r
237 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
238 @param[in] Port The port number of the ATA device to send the command.\r
239 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
240 If there is no port multiplier, then specify 0xFFFF.\r
241\r
242 @retval EFI_SUCCESS Successful to send freeze lock cmd.\r
243 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
244 @retval EFI_OUT_OF_RESOURCES Not enough memory to send freeze lock cmd.\r
245 @retval EFI_DEVICE_ERROR Can not send freeze lock cmd.\r
246\r
247**/\r
248EFI_STATUS\r
249FreezeLockDevice (\r
250 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
251 IN UINT16 Port,\r
252 IN UINT16 PortMultiplierPort\r
253 )\r
254{\r
255 EFI_STATUS Status;\r
256 EFI_ATA_COMMAND_BLOCK Acb;\r
257 EFI_ATA_STATUS_BLOCK *Asb;\r
258 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
259\r
260 if (AtaPassThru == NULL) {\r
261 return EFI_INVALID_PARAMETER;\r
262 }\r
263\r
264 //\r
265 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
266 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
267 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
268 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
269 // may not be aligned when allocated on stack for some compilers. Hence, we\r
270 // use the API AllocateAlignedPages to ensure this structure is properly\r
271 // aligned.\r
272 //\r
273 Asb = AllocateAlignedPages (\r
274 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
275 AtaPassThru->Mode->IoAlign\r
276 );\r
277 if (Asb == NULL) {\r
278 return EFI_OUT_OF_RESOURCES;\r
279 }\r
280\r
281 //\r
282 // Prepare for ATA command block.\r
283 //\r
284 ZeroMem (&Acb, sizeof (Acb));\r
285 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
286 Acb.AtaCommand = ATA_SECURITY_FREEZE_LOCK_CMD;\r
287 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
288\r
289 //\r
290 // Prepare for ATA pass through packet.\r
291 //\r
292 ZeroMem (&Packet, sizeof (Packet));\r
293 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;\r
294 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_NO_DATA_TRANSFER;\r
295 Packet.Asb = Asb;\r
296 Packet.Acb = &Acb;\r
297 Packet.Timeout = ATA_TIMEOUT;\r
298\r
299 Status = AtaPassThru->PassThru (\r
300 AtaPassThru,\r
301 Port,\r
302 PortMultiplierPort,\r
303 &Packet,\r
304 NULL\r
305 );\r
306 if (!EFI_ERROR (Status) &&\r
307 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
308 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
309 Status = EFI_DEVICE_ERROR;\r
310 }\r
311\r
312 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
313\r
314 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
315 return Status;\r
316}\r
317\r
318/**\r
319 Get attached harddisk identify data through Ata Pass Thru Protocol.\r
320\r
321 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
322 @param[in] Port The port number of the ATA device to send the command.\r
323 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
324 If there is no port multiplier, then specify 0xFFFF.\r
325 @param[in] IdentifyData The buffer to store identify data.\r
326\r
327 @retval EFI_SUCCESS Successful to get identify data.\r
328 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
329 @retval EFI_OUT_OF_RESOURCES Not enough memory to get identify data.\r
330 @retval EFI_DEVICE_ERROR Can not get identify data.\r
331\r
332**/\r
333EFI_STATUS\r
334GetHddDeviceIdentifyData (\r
335 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
336 IN UINT16 Port,\r
337 IN UINT16 PortMultiplierPort,\r
338 IN ATA_IDENTIFY_DATA *IdentifyData\r
339 )\r
340{\r
341 EFI_STATUS Status;\r
342 EFI_ATA_COMMAND_BLOCK Acb;\r
343 EFI_ATA_STATUS_BLOCK *Asb;\r
344 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
345\r
346 if ((AtaPassThru == NULL) || (IdentifyData == NULL)) {\r
347 return EFI_INVALID_PARAMETER;\r
348 }\r
349\r
350 //\r
351 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
352 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
353 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
354 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
355 // may not be aligned when allocated on stack for some compilers. Hence, we\r
356 // use the API AllocateAlignedPages to ensure this structure is properly\r
357 // aligned.\r
358 //\r
359 Asb = AllocateAlignedPages (\r
360 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
361 AtaPassThru->Mode->IoAlign\r
362 );\r
363 if (Asb == NULL) {\r
364 return EFI_OUT_OF_RESOURCES;\r
365 }\r
366\r
367 //\r
368 // Prepare for ATA command block.\r
369 //\r
370 ZeroMem (&Acb, sizeof (Acb));\r
371 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
372 Acb.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
373 Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 | (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4)));\r
374\r
375 //\r
376 // Prepare for ATA pass through packet.\r
377 //\r
378 ZeroMem (&Packet, sizeof (Packet));\r
379 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN;\r
380 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES | EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT;\r
381 Packet.Asb = Asb;\r
382 Packet.Acb = &Acb;\r
383 Packet.InDataBuffer = IdentifyData;\r
384 Packet.InTransferLength = sizeof (ATA_IDENTIFY_DATA);\r
385 Packet.Timeout = ATA_TIMEOUT;\r
386\r
387 Status = AtaPassThru->PassThru (\r
388 AtaPassThru,\r
389 Port,\r
390 PortMultiplierPort,\r
391 &Packet,\r
392 NULL\r
393 );\r
394\r
395 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
396\r
397 return Status;\r
398}\r
399\r
400/**\r
401 Parse security status according to identify data.\r
402\r
403 @param[in] IdentifyData The buffer to store identify data.\r
404 @param[in, out] IfrData IFR data to hold security status.\r
405\r
406**/\r
407VOID\r
408GetHddPasswordSecurityStatus (\r
409 IN ATA_IDENTIFY_DATA *IdentifyData,\r
410 IN OUT HDD_PASSWORD_CONFIG *IfrData\r
411 )\r
412{\r
413 IfrData->SecurityStatus.Supported = (IdentifyData->command_set_supported_82 & BIT1) ? 1 : 0;\r
414 IfrData->SecurityStatus.Enabled = (IdentifyData->security_status & BIT1) ? 1 : 0;\r
415 IfrData->SecurityStatus.Locked = (IdentifyData->security_status & BIT2) ? 1 : 0;\r
416 IfrData->SecurityStatus.Frozen = (IdentifyData->security_status & BIT3) ? 1 : 0;\r
417 IfrData->SecurityStatus.UserPasswordStatus = IfrData->SecurityStatus.Enabled;\r
418 IfrData->SecurityStatus.MasterPasswordStatus = IfrData->SecurityStatus.Supported;\r
419\r
420 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Supported = %x\n", IfrData->SecurityStatus.Supported));\r
421 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Enabled = %x\n", IfrData->SecurityStatus.Enabled));\r
422 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Locked = %x\n", IfrData->SecurityStatus.Locked));\r
423 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.Frozen = %x\n", IfrData->SecurityStatus.Frozen));\r
424 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.UserPasswordStatus = %x\n", IfrData->SecurityStatus.UserPasswordStatus));\r
425 DEBUG ((DEBUG_INFO, "IfrData->SecurityStatus.MasterPasswordStatus = %x\n", IfrData->SecurityStatus.MasterPasswordStatus));\r
426}\r
427\r
428/**\r
429 Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
430\r
431 This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
432\r
433 @param Event Event whose notification function is being invoked.\r
434 @param Context Pointer to the notification function's context.\r
435\r
436**/\r
437VOID\r
438EFIAPI\r
439HddPasswordEndOfDxeEventNotify (\r
440 EFI_EVENT Event,\r
441 VOID *Context\r
442 )\r
443{\r
444 LIST_ENTRY *Entry;\r
445 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
446 EFI_STATUS Status;\r
447 ATA_IDENTIFY_DATA IdentifyData;\r
448\r
449 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
450\r
451 mHddPasswordEndOfDxe = TRUE;\r
452\r
453 if (mHddPasswordRequestVariable != NULL) {\r
454 //\r
455 // Free the HDD password request variable buffer here\r
456 // as the HDD password requests should have been processed.\r
457 //\r
458 FreePool (mHddPasswordRequestVariable);\r
459 mHddPasswordRequestVariable = NULL;\r
460 mHddPasswordRequestVariableSize = 0;\r
461 }\r
462\r
463 //\r
464 // If no any device, return directly.\r
465 //\r
466 if (IsListEmpty (&mHddPasswordConfigFormList)) {\r
467 gBS->CloseEvent (Event);\r
468 return;\r
469 }\r
470\r
471 BuildHddPasswordDeviceInfo ();\r
472\r
473 //\r
474 // Zero passsword and freeze lock device.\r
475 //\r
3571e136 476 BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
e8959f81
HW
477 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
478\r
479 ZeroMem (ConfigFormEntry->Password, HDD_PASSWORD_MAX_LENGTH);\r
480\r
481 //\r
482 // Check whether need send freeze lock command.\r
483 // Below device will be froze:\r
484 // 1. Device not enable password.\r
485 // 2. Device enable password and unlocked.\r
486 //\r
487 if ((ConfigFormEntry->IfrData.SecurityStatus.Supported != 0) &&\r
488 (ConfigFormEntry->IfrData.SecurityStatus.Locked == 0) &&\r
489 (ConfigFormEntry->IfrData.SecurityStatus.Frozen == 0)) {\r
490 Status = FreezeLockDevice (ConfigFormEntry->AtaPassThru, ConfigFormEntry->Port, ConfigFormEntry->PortMultiplierPort);\r
491 DEBUG ((DEBUG_INFO, "FreezeLockDevice return %r!\n", Status));\r
492 Status = GetHddDeviceIdentifyData (\r
493 ConfigFormEntry->AtaPassThru,\r
494 ConfigFormEntry->Port,\r
495 ConfigFormEntry->PortMultiplierPort,\r
496 &IdentifyData\r
497 );\r
498 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
499 }\r
500 }\r
501\r
502 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
503\r
504 gBS->CloseEvent (Event);\r
505}\r
506\r
507/**\r
508 Generate Salt value.\r
509\r
510 @param[in, out] SaltValue Points to the salt buffer, 32 bytes\r
511\r
512**/\r
513VOID\r
514GenSalt (\r
515 IN OUT UINT8 *SaltValue\r
516 )\r
517{\r
518 RandomSeed (NULL, 0);\r
519 RandomBytes (SaltValue, PASSWORD_SALT_SIZE);\r
520}\r
521\r
522/**\r
523 Hash the data to get credential.\r
524\r
525 @param[in] Buffer Points to the data buffer\r
526 @param[in] BufferSize Buffer size\r
527 @param[in] SaltValue Points to the salt buffer, 32 bytes\r
528 @param[out] Credential Points to the hashed result\r
529\r
530 @retval TRUE Hash the data successfully.\r
531 @retval FALSE Failed to hash the data.\r
532\r
533**/\r
534BOOLEAN\r
535GenerateCredential (\r
536 IN UINT8 *Buffer,\r
537 IN UINTN BufferSize,\r
538 IN UINT8 *SaltValue,\r
539 OUT UINT8 *Credential\r
540 )\r
541{\r
542 BOOLEAN Status;\r
543 UINTN HashSize;\r
544 VOID *Hash;\r
545 VOID *HashData;\r
546\r
547 Hash = NULL;\r
548 HashData = NULL;\r
549 Status = FALSE;\r
550\r
551 HashSize = Sha256GetContextSize ();\r
552 Hash = AllocateZeroPool (HashSize);\r
553 ASSERT (Hash != NULL);\r
554 if (Hash == NULL) {\r
555 goto Done;\r
556 }\r
557\r
558 Status = Sha256Init (Hash);\r
559 if (!Status) {\r
560 goto Done;\r
561 }\r
562\r
563 HashData = AllocateZeroPool (PASSWORD_SALT_SIZE + BufferSize);\r
564 ASSERT (HashData != NULL);\r
565 if (HashData == NULL) {\r
566 goto Done;\r
567 }\r
568\r
569 CopyMem (HashData, SaltValue, PASSWORD_SALT_SIZE);\r
570 CopyMem ((UINT8 *) HashData + PASSWORD_SALT_SIZE, Buffer, BufferSize);\r
571\r
572 Status = Sha256Update (Hash, HashData, PASSWORD_SALT_SIZE + BufferSize);\r
573 if (!Status) {\r
574 goto Done;\r
575 }\r
576\r
577 Status = Sha256Final (Hash, Credential);\r
578\r
579Done:\r
580 if (Hash != NULL) {\r
581 FreePool (Hash);\r
582 }\r
583 if (HashData != NULL) {\r
584 ZeroMem (HashData, PASSWORD_SALT_SIZE + BufferSize);\r
585 FreePool (HashData);\r
586 }\r
587 return Status;\r
588}\r
589\r
590/**\r
591 Save HDD password variable that will be used to validate HDD password\r
592 when the device is at frozen state.\r
593\r
594 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
595 @param[in] Password The hdd password of attached ATA device.\r
596\r
597**/\r
598VOID\r
599SaveHddPasswordVariable (\r
600 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
601 IN CHAR8 *Password\r
602 )\r
603{\r
604 EFI_STATUS Status;\r
605 HDD_PASSWORD_VARIABLE *TempVariable;\r
606 UINTN TempVariableSize;\r
607 HDD_PASSWORD_VARIABLE *NextNode;\r
608 HDD_PASSWORD_VARIABLE *Variable;\r
609 UINTN VariableSize;\r
610 HDD_PASSWORD_VARIABLE *NewVariable;\r
611 UINTN NewVariableSize;\r
612 BOOLEAN Delete;\r
613 BOOLEAN HashOk;\r
614 UINT8 HashData[SHA256_DIGEST_SIZE];\r
615 UINT8 SaltData[PASSWORD_SALT_SIZE];\r
616\r
617 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
618\r
619 Delete = FALSE;\r
620 if (!PasswordIsFullZero (Password)) {\r
621 //\r
622 // It is Set/Update HDD Password.\r
623 //\r
624 ZeroMem (HashData, sizeof (HashData));\r
625 ZeroMem (SaltData, sizeof (SaltData));\r
626 GenSalt (SaltData);\r
627 HashOk = GenerateCredential ((UINT8 *) Password, HDD_PASSWORD_MAX_LENGTH, SaltData, HashData);\r
628 if (!HashOk) {\r
629 DEBUG ((DEBUG_INFO, "GenerateCredential failed\n"));\r
630 return;\r
631 }\r
632 } else {\r
633 //\r
634 // It is Disable HDD Password.\r
635 // Go to delete the variable node for the HDD password device.\r
636 //\r
637 Delete = TRUE;\r
638 }\r
639\r
640 Variable = NULL;\r
641 VariableSize = 0;\r
642 NewVariable = NULL;\r
643 NewVariableSize = 0;\r
644\r
645 Status = GetVariable2 (\r
646 HDD_PASSWORD_VARIABLE_NAME,\r
647 &mHddPasswordVendorGuid,\r
648 (VOID **) &Variable,\r
649 &VariableSize\r
650 );\r
651 if (Delete) {\r
652 if (!EFI_ERROR (Status) && (Variable != NULL)) {\r
653 TempVariable = Variable;\r
654 TempVariableSize = VariableSize;\r
655 while (TempVariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {\r
656 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
657 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
658 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
659 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
660 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
661 //\r
662 // Found the node for the HDD password device.\r
663 // Delete the node.\r
664 //\r
665 NextNode = TempVariable + 1;\r
666 CopyMem (TempVariable, NextNode, (UINTN) Variable + VariableSize - (UINTN) NextNode);\r
667 NewVariable = Variable;\r
668 NewVariableSize = VariableSize - sizeof (HDD_PASSWORD_VARIABLE);\r
669 break;\r
670 }\r
671 TempVariableSize -= sizeof (HDD_PASSWORD_VARIABLE);\r
672 TempVariable += 1;\r
673 }\r
674 if (NewVariable == NULL) {\r
675 DEBUG ((DEBUG_INFO, "The variable node for the HDD password device is not found\n"));\r
676 }\r
677 } else {\r
678 DEBUG ((DEBUG_INFO, "HddPassword variable get failed (%r)\n", Status));\r
679 }\r
680 } else {\r
681 if (!EFI_ERROR (Status) && (Variable != NULL)) {\r
682 TempVariable = Variable;\r
683 TempVariableSize = VariableSize;\r
684 while (TempVariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {\r
685 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
686 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
687 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
688 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
689 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
690 //\r
691 // Found the node for the HDD password device.\r
692 // Update the node.\r
693 //\r
694 CopyMem (TempVariable->PasswordHash, HashData, sizeof (HashData));\r
695 CopyMem (TempVariable->PasswordSalt, SaltData, sizeof (SaltData));\r
696 NewVariable = Variable;\r
697 NewVariableSize = VariableSize;\r
698 break;\r
699 }\r
700 TempVariableSize -= sizeof (HDD_PASSWORD_VARIABLE);\r
701 TempVariable += 1;\r
702 }\r
703 if (NewVariable == NULL) {\r
704 //\r
705 // The node for the HDD password device is not found.\r
706 // Create node for the HDD password device.\r
707 //\r
708 NewVariableSize = VariableSize + sizeof (HDD_PASSWORD_VARIABLE);\r
709 NewVariable = AllocateZeroPool (NewVariableSize);\r
710 ASSERT (NewVariable != NULL);\r
711 CopyMem (NewVariable, Variable, VariableSize);\r
712 TempVariable = (HDD_PASSWORD_VARIABLE *) ((UINTN) NewVariable + VariableSize);\r
713 TempVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
714 TempVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
715 TempVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
716 TempVariable->Device.Port = ConfigFormEntry->Port;\r
717 TempVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
718 CopyMem (TempVariable->PasswordHash, HashData, sizeof (HashData));\r
719 CopyMem (TempVariable->PasswordSalt, SaltData, sizeof (SaltData));\r
720 }\r
721 } else {\r
722 NewVariableSize = sizeof (HDD_PASSWORD_VARIABLE);\r
723 NewVariable = AllocateZeroPool (NewVariableSize);\r
724 ASSERT (NewVariable != NULL);\r
725 NewVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
726 NewVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
727 NewVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
728 NewVariable->Device.Port = ConfigFormEntry->Port;\r
729 NewVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
730 CopyMem (NewVariable->PasswordHash, HashData, sizeof (HashData));\r
731 CopyMem (NewVariable->PasswordSalt, SaltData, sizeof (SaltData));\r
732 }\r
733 }\r
734\r
735 if (NewVariable != NULL) {\r
736 Status = gRT->SetVariable (\r
737 HDD_PASSWORD_VARIABLE_NAME,\r
738 &mHddPasswordVendorGuid,\r
739 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
740 NewVariableSize,\r
741 NewVariable\r
742 );\r
743 if (EFI_ERROR (Status)) {\r
744 DEBUG ((DEBUG_INFO, "HddPassword variable set failed (%r)\n", Status));\r
745 }\r
746 }\r
747\r
748 if (NewVariable != Variable) {\r
749 FreePool (NewVariable);\r
750 }\r
751 if (Variable != NULL) {\r
752 FreePool (Variable);\r
753 }\r
754\r
755 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
756}\r
757\r
758/**\r
759 Get saved HDD password variable that will be used to validate HDD password\r
760 when the device is at frozen state.\r
761\r
762 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
763 @param[out] HddPasswordVariable The variable node for the HDD password device.\r
764\r
765 @retval TRUE The variable node for the HDD password device is found and returned.\r
766 @retval FALSE The variable node for the HDD password device is not found.\r
767\r
768**/\r
769BOOLEAN\r
770GetSavedHddPasswordVariable (\r
771 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
772 OUT HDD_PASSWORD_VARIABLE *HddPasswordVariable\r
773 )\r
774{\r
775 EFI_STATUS Status;\r
776 HDD_PASSWORD_VARIABLE *TempVariable;\r
777 HDD_PASSWORD_VARIABLE *Variable;\r
778 UINTN VariableSize;\r
779 BOOLEAN Found;\r
780\r
781 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
782\r
783 Variable = NULL;\r
784 VariableSize = 0;\r
785\r
786 Status = GetVariable2 (\r
787 HDD_PASSWORD_VARIABLE_NAME,\r
788 &mHddPasswordVendorGuid,\r
789 (VOID **) &Variable,\r
790 &VariableSize\r
791 );\r
792 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
793 DEBUG ((DEBUG_INFO, "HddPassword variable get failed (%r)\n", Status));\r
794 return FALSE;\r
795 }\r
796\r
797 Found = FALSE;\r
798 TempVariable = Variable;\r
799 while (VariableSize >= sizeof (HDD_PASSWORD_VARIABLE)) {\r
800 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
801 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
802 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
803 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
804 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
805 //\r
806 // Found the node for the HDD password device.\r
807 // Get the node.\r
808 //\r
809 CopyMem (HddPasswordVariable, TempVariable, sizeof (HDD_PASSWORD_VARIABLE));\r
810 Found = TRUE;\r
811 break;\r
812 }\r
813 VariableSize -= sizeof (HDD_PASSWORD_VARIABLE);\r
814 TempVariable += 1;\r
815 }\r
816\r
817 FreePool (Variable);\r
818\r
819 if (!Found) {\r
820 DEBUG ((DEBUG_INFO, "The variable node for the HDD password device is not found\n"));\r
821 }\r
822\r
823 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
824\r
825 return Found;\r
826}\r
827\r
828/**\r
829 Use saved HDD password variable to validate HDD password\r
830 when the device is at frozen state.\r
831\r
832 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
833 @param[in] Password The hdd password of attached ATA device.\r
834\r
835 @retval EFI_SUCCESS Pass to validate the HDD password.\r
836 @retval EFI_NOT_FOUND The variable node for the HDD password device is not found.\r
837 @retval EFI_DEVICE_ERROR Failed to generate credential for the HDD password.\r
838 @retval EFI_INVALID_PARAMETER Failed to validate the HDD password.\r
839\r
840**/\r
841EFI_STATUS\r
842ValidateHddPassword (\r
843 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
844 IN CHAR8 *Password\r
845 )\r
846{\r
847 EFI_STATUS Status;\r
848 HDD_PASSWORD_VARIABLE HddPasswordVariable;\r
849 BOOLEAN HashOk;\r
850 UINT8 HashData[SHA256_DIGEST_SIZE];\r
851\r
852 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
853\r
854 if (!GetSavedHddPasswordVariable (ConfigFormEntry, &HddPasswordVariable)) {\r
855 DEBUG ((DEBUG_INFO, "GetSavedHddPasswordVariable failed\n"));\r
856 return EFI_NOT_FOUND;\r
857 }\r
858\r
859 ZeroMem (HashData, sizeof (HashData));\r
860 HashOk = GenerateCredential ((UINT8 *) Password, HDD_PASSWORD_MAX_LENGTH, HddPasswordVariable.PasswordSalt, HashData);\r
861 if (!HashOk) {\r
862 DEBUG ((DEBUG_INFO, "GenerateCredential failed\n"));\r
863 return EFI_DEVICE_ERROR;\r
864 }\r
865\r
866 if (CompareMem (HddPasswordVariable.PasswordHash, HashData, sizeof (HashData)) != 0) {\r
867 Status = EFI_INVALID_PARAMETER;\r
868 } else {\r
869 Status = EFI_SUCCESS;\r
870 }\r
871\r
872 DEBUG ((DEBUG_INFO, "%a() - exit (%r)\n", __FUNCTION__, Status));\r
873 return Status;\r
874}\r
875\r
876/**\r
877 Send unlock hdd password cmd through Ata Pass Thru Protocol.\r
878\r
879 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
880 @param[in] Port The port number of the ATA device to send the command.\r
881 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
882 If there is no port multiplier, then specify 0xFFFF.\r
883 @param[in] Identifier The identifier to set user or master password.\r
884 @param[in] Password The hdd password of attached ATA device.\r
885\r
886 @retval EFI_SUCCESS Successful to send unlock hdd password cmd.\r
887 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
888 @retval EFI_OUT_OF_RESOURCES Not enough memory to send unlock hdd password cmd.\r
889 @retval EFI_DEVICE_ERROR Can not send unlock hdd password cmd.\r
890\r
891**/\r
892EFI_STATUS\r
893UnlockHddPassword (\r
894 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
895 IN UINT16 Port,\r
896 IN UINT16 PortMultiplierPort,\r
897 IN CHAR8 Identifier,\r
898 IN CHAR8 *Password\r
899 )\r
900{\r
901 EFI_STATUS Status;\r
902 EFI_ATA_COMMAND_BLOCK Acb;\r
903 EFI_ATA_STATUS_BLOCK *Asb;\r
904 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
905 UINT8 Buffer[HDD_PAYLOAD];\r
906\r
907 if ((AtaPassThru == NULL) || (Password == NULL)) {\r
908 return EFI_INVALID_PARAMETER;\r
909 }\r
910\r
911 //\r
912 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
913 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
914 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
915 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
916 // may not be aligned when allocated on stack for some compilers. Hence, we\r
917 // use the API AllocateAlignedPages to ensure this structure is properly\r
918 // aligned.\r
919 //\r
920 Asb = AllocateAlignedPages (\r
921 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
922 AtaPassThru->Mode->IoAlign\r
923 );\r
924 if (Asb == NULL) {\r
925 return EFI_OUT_OF_RESOURCES;\r
926 }\r
927\r
928 //\r
929 // Prepare for ATA command block.\r
930 //\r
931 ZeroMem (&Acb, sizeof (Acb));\r
932 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
933 Acb.AtaCommand = ATA_SECURITY_UNLOCK_CMD;\r
934 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
935\r
936 //\r
937 // Prepare for ATA pass through packet.\r
938 //\r
939 ZeroMem (&Packet, sizeof (Packet));\r
940 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;\r
941 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
942 Packet.Asb = Asb;\r
943 Packet.Acb = &Acb;\r
944\r
945 ((CHAR16 *) Buffer)[0] = Identifier & BIT0;\r
946 CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);\r
947\r
948 Packet.OutDataBuffer = Buffer;\r
949 Packet.OutTransferLength = sizeof (Buffer);\r
950 Packet.Timeout = ATA_TIMEOUT;\r
951\r
952 Status = AtaPassThru->PassThru (\r
953 AtaPassThru,\r
954 Port,\r
955 PortMultiplierPort,\r
956 &Packet,\r
957 NULL\r
958 );\r
959 if (!EFI_ERROR (Status) &&\r
960 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
961 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
962 Status = EFI_DEVICE_ERROR;\r
963 }\r
964\r
965 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
966\r
967 ZeroMem (Buffer, sizeof (Buffer));\r
968\r
969 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
970 return Status;\r
971}\r
972\r
973/**\r
974 Send disable hdd password cmd through Ata Pass Thru Protocol.\r
975\r
976 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
977 @param[in] Port The port number of the ATA device to send the command.\r
978 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
979 If there is no port multiplier, then specify 0xFFFF.\r
980 @param[in] Identifier The identifier to set user or master password.\r
981 @param[in] Password The hdd password of attached ATA device.\r
982\r
983 @retval EFI_SUCCESS Successful to disable hdd password cmd.\r
984 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
985 @retval EFI_OUT_OF_RESOURCES Not enough memory to disable hdd password cmd.\r
986 @retval EFI_DEVICE_ERROR Can not disable hdd password cmd.\r
987\r
988**/\r
989EFI_STATUS\r
990DisableHddPassword (\r
991 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
992 IN UINT16 Port,\r
993 IN UINT16 PortMultiplierPort,\r
994 IN CHAR8 Identifier,\r
995 IN CHAR8 *Password\r
996 )\r
997{\r
998 EFI_STATUS Status;\r
999 EFI_ATA_COMMAND_BLOCK Acb;\r
1000 EFI_ATA_STATUS_BLOCK *Asb;\r
1001 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
1002 UINT8 Buffer[HDD_PAYLOAD];\r
1003\r
1004 if ((AtaPassThru == NULL) || (Password == NULL)) {\r
1005 return EFI_INVALID_PARAMETER;\r
1006 }\r
1007\r
1008 //\r
1009 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
1010 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
1011 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
1012 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
1013 // may not be aligned when allocated on stack for some compilers. Hence, we\r
1014 // use the API AllocateAlignedPages to ensure this structure is properly\r
1015 // aligned.\r
1016 //\r
1017 Asb = AllocateAlignedPages (\r
1018 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
1019 AtaPassThru->Mode->IoAlign\r
1020 );\r
1021 if (Asb == NULL) {\r
1022 return EFI_OUT_OF_RESOURCES;\r
1023 }\r
1024\r
1025 //\r
1026 // Prepare for ATA command block.\r
1027 //\r
1028 ZeroMem (&Acb, sizeof (Acb));\r
1029 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
1030 Acb.AtaCommand = ATA_SECURITY_DIS_PASSWORD_CMD;\r
1031 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
1032\r
1033 //\r
1034 // Prepare for ATA pass through packet.\r
1035 //\r
1036 ZeroMem (&Packet, sizeof (Packet));\r
1037 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;\r
1038 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
1039 Packet.Asb = Asb;\r
1040 Packet.Acb = &Acb;\r
1041\r
1042 ((CHAR16 *) Buffer)[0] = Identifier & BIT0;\r
1043 CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);\r
1044\r
1045 Packet.OutDataBuffer = Buffer;\r
1046 Packet.OutTransferLength = sizeof (Buffer);\r
1047 Packet.Timeout = ATA_TIMEOUT;\r
1048\r
1049 Status = AtaPassThru->PassThru (\r
1050 AtaPassThru,\r
1051 Port,\r
1052 PortMultiplierPort,\r
1053 &Packet,\r
1054 NULL\r
1055 );\r
1056 if (!EFI_ERROR (Status) &&\r
1057 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
1058 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
1059 Status = EFI_DEVICE_ERROR;\r
1060 }\r
1061\r
1062 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
1063\r
1064 ZeroMem (Buffer, sizeof (Buffer));\r
1065\r
1066 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
1067 return Status;\r
1068}\r
1069\r
1070/**\r
1071 Send set hdd password cmd through Ata Pass Thru Protocol.\r
1072\r
1073 @param[in] AtaPassThru The pointer to the ATA_PASS_THRU protocol.\r
1074 @param[in] Port The port number of the ATA device to send the command.\r
1075 @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.\r
1076 If there is no port multiplier, then specify 0xFFFF.\r
1077 @param[in] Identifier The identifier to set user or master password.\r
1078 @param[in] SecurityLevel The security level to be set to device.\r
1079 @param[in] MasterPasswordIdentifier The master password identifier to be set to device.\r
1080 @param[in] Password The hdd password of attached ATA device.\r
1081\r
1082 @retval EFI_SUCCESS Successful to set hdd password cmd.\r
1083 @retval EFI_INVALID_PARAMETER The parameter passed-in is invalid.\r
1084 @retval EFI_OUT_OF_RESOURCES Not enough memory to set hdd password cmd.\r
1085 @retval EFI_DEVICE_ERROR Can not set hdd password cmd.\r
1086\r
1087**/\r
1088EFI_STATUS\r
1089SetHddPassword (\r
1090 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1091 IN UINT16 Port,\r
1092 IN UINT16 PortMultiplierPort,\r
1093 IN CHAR8 Identifier,\r
1094 IN CHAR8 SecurityLevel,\r
1095 IN CHAR16 MasterPasswordIdentifier,\r
1096 IN CHAR8 *Password\r
1097 )\r
1098{\r
1099 EFI_STATUS Status;\r
1100 EFI_ATA_COMMAND_BLOCK Acb;\r
1101 EFI_ATA_STATUS_BLOCK *Asb;\r
1102 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;\r
1103 UINT8 Buffer[HDD_PAYLOAD];\r
1104\r
1105 if ((AtaPassThru == NULL) || (Password == NULL)) {\r
1106 return EFI_INVALID_PARAMETER;\r
1107 }\r
1108\r
1109 //\r
1110 // The 'Asb' field (a pointer to the EFI_ATA_STATUS_BLOCK structure) in\r
1111 // EFI_ATA_PASS_THRU_COMMAND_PACKET is required to be aligned specified by\r
1112 // the 'IoAlign' field in the EFI_ATA_PASS_THRU_MODE structure. Meanwhile,\r
1113 // the structure EFI_ATA_STATUS_BLOCK is composed of only UINT8 fields, so it\r
1114 // may not be aligned when allocated on stack for some compilers. Hence, we\r
1115 // use the API AllocateAlignedPages to ensure this structure is properly\r
1116 // aligned.\r
1117 //\r
1118 Asb = AllocateAlignedPages (\r
1119 EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)),\r
1120 AtaPassThru->Mode->IoAlign\r
1121 );\r
1122 if (Asb == NULL) {\r
1123 return EFI_OUT_OF_RESOURCES;\r
1124 }\r
1125\r
1126 //\r
1127 // Prepare for ATA command block.\r
1128 //\r
1129 ZeroMem (&Acb, sizeof (Acb));\r
1130 ZeroMem (Asb, sizeof (EFI_ATA_STATUS_BLOCK));\r
1131 Acb.AtaCommand = ATA_SECURITY_SET_PASSWORD_CMD;\r
1132 Acb.AtaDeviceHead = (UINT8) (PortMultiplierPort == 0xFFFF ? 0 : (PortMultiplierPort << 4));\r
1133\r
1134 //\r
1135 // Prepare for ATA pass through packet.\r
1136 //\r
1137 ZeroMem (&Packet, sizeof (Packet));\r
1138 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT;\r
1139 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;\r
1140 Packet.Asb = Asb;\r
1141 Packet.Acb = &Acb;\r
1142\r
1143 ((CHAR16 *) Buffer)[0] = (Identifier | (UINT16)(SecurityLevel << 8)) & (BIT0 | BIT8);\r
1144 CopyMem (&((CHAR16 *) Buffer)[1], Password, HDD_PASSWORD_MAX_LENGTH);\r
1145 if ((Identifier & BIT0) != 0) {\r
1146 ((CHAR16 *) Buffer)[17] = MasterPasswordIdentifier;\r
1147 }\r
1148\r
1149 Packet.OutDataBuffer = Buffer;\r
1150 Packet.OutTransferLength = sizeof (Buffer);\r
1151 Packet.Timeout = ATA_TIMEOUT;\r
1152\r
1153 Status = AtaPassThru->PassThru (\r
1154 AtaPassThru,\r
1155 Port,\r
1156 PortMultiplierPort,\r
1157 &Packet,\r
1158 NULL\r
1159 );\r
1160 if (!EFI_ERROR (Status) &&\r
1161 ((Asb->AtaStatus & ATA_STSREG_ERR) != 0) &&\r
1162 ((Asb->AtaError & ATA_ERRREG_ABRT) != 0)) {\r
1163 Status = EFI_DEVICE_ERROR;\r
1164 }\r
1165\r
1166 FreeAlignedPages (Asb, EFI_SIZE_TO_PAGES (sizeof (EFI_ATA_STATUS_BLOCK)));\r
1167\r
1168 ZeroMem (Buffer, sizeof (Buffer));\r
1169\r
1170 DEBUG ((DEBUG_INFO, "%a() - %r\n", __FUNCTION__, Status));\r
1171 return Status;\r
1172}\r
1173\r
1174/**\r
1175 Get attached harddisk model number from identify data buffer.\r
1176\r
1177 @param[in] IdentifyData Pointer to identify data buffer.\r
1178 @param[in, out] String The buffer to store harddisk model number.\r
1179\r
1180**/\r
1181VOID\r
1182GetHddDeviceModelNumber (\r
1183 IN ATA_IDENTIFY_DATA *IdentifyData,\r
1184 IN OUT CHAR16 *String\r
1185 )\r
1186{\r
1187 UINTN Index;\r
1188\r
1189 //\r
1190 // Swap the byte order in the original module name.\r
1191 // From Ata spec, the maximum length is 40 bytes.\r
1192 //\r
1193 for (Index = 0; Index < 40; Index += 2) {\r
1194 String[Index] = IdentifyData->ModelName[Index + 1];\r
1195 String[Index + 1] = IdentifyData->ModelName[Index];\r
1196 }\r
1197\r
1198 //\r
1199 // Chap it off after 20 characters\r
1200 //\r
1201 String[20] = L'\0';\r
1202\r
1203 return ;\r
1204}\r
1205\r
1206/**\r
1207 Get password input from the popup windows.\r
1208\r
1209 @param[in] PopUpString1 Pop up string 1.\r
1210 @param[in] PopUpString2 Pop up string 2.\r
1211 @param[in, out] Password The buffer to hold the input password.\r
1212\r
1213 @retval EFI_ABORTED It is given up by pressing 'ESC' key.\r
1214 @retval EFI_SUCCESS Get password input successfully.\r
1215\r
1216**/\r
1217EFI_STATUS\r
1218PopupHddPasswordInputWindows (\r
1219 IN CHAR16 *PopUpString1,\r
1220 IN CHAR16 *PopUpString2,\r
1221 IN OUT CHAR8 *Password\r
1222 )\r
1223{\r
1224 EFI_INPUT_KEY Key;\r
1225 UINTN Length;\r
1226 CHAR16 Mask[HDD_PASSWORD_MAX_LENGTH + 1];\r
1227 CHAR16 Unicode[HDD_PASSWORD_MAX_LENGTH + 1];\r
1228 CHAR8 Ascii[HDD_PASSWORD_MAX_LENGTH + 1];\r
1229\r
1230 ZeroMem (Unicode, sizeof (Unicode));\r
1231 ZeroMem (Ascii, sizeof (Ascii));\r
1232 ZeroMem (Mask, sizeof (Mask));\r
1233\r
1234 gST->ConOut->ClearScreen(gST->ConOut);\r
1235\r
1236 Length = 0;\r
1237 while (TRUE) {\r
1238 Mask[Length] = L'_';\r
1239 if (PopUpString2 == NULL) {\r
1240 CreatePopUp (\r
1241 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1242 &Key,\r
1243 PopUpString1,\r
1244 L"---------------------",\r
1245 Mask,\r
1246 NULL\r
1247 );\r
1248 } else {\r
1249 CreatePopUp (\r
1250 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1251 &Key,\r
1252 PopUpString1,\r
1253 PopUpString2,\r
1254 L"---------------------",\r
1255 Mask,\r
1256 NULL\r
1257 );\r
1258 }\r
1259 //\r
1260 // Check key.\r
1261 //\r
1262 if (Key.ScanCode == SCAN_NULL) {\r
1263 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1264 //\r
1265 // Add the null terminator.\r
1266 //\r
1267 Unicode[Length] = 0;\r
1268 break;\r
1269 } else if ((Key.UnicodeChar == CHAR_NULL) ||\r
1270 (Key.UnicodeChar == CHAR_TAB) ||\r
1271 (Key.UnicodeChar == CHAR_LINEFEED)\r
1272 ) {\r
1273 continue;\r
1274 } else {\r
1275 if (Key.UnicodeChar == CHAR_BACKSPACE) {\r
1276 if (Length > 0) {\r
1277 Unicode[Length] = 0;\r
1278 Mask[Length] = 0;\r
1279 Length--;\r
1280 }\r
1281 } else {\r
1282 Unicode[Length] = Key.UnicodeChar;\r
1283 Mask[Length] = L'*';\r
1284 Length++;\r
1285 if (Length == HDD_PASSWORD_MAX_LENGTH) {\r
1286 //\r
1287 // Add the null terminator.\r
1288 //\r
1289 Unicode[Length] = 0;\r
1290 Mask[Length] = 0;\r
1291 break;\r
1292 }\r
1293 }\r
1294 }\r
1295 }\r
1296\r
1297 if (Key.ScanCode == SCAN_ESC) {\r
1298 ZeroMem (Unicode, sizeof (Unicode));\r
1299 ZeroMem (Ascii, sizeof (Ascii));\r
1300 gST->ConOut->ClearScreen(gST->ConOut);\r
1301 return EFI_ABORTED;\r
1302 }\r
1303 }\r
1304\r
1305 UnicodeStrToAsciiStrS (Unicode, Ascii, sizeof (Ascii));\r
1306 CopyMem (Password, Ascii, HDD_PASSWORD_MAX_LENGTH);\r
1307 ZeroMem (Unicode, sizeof (Unicode));\r
1308 ZeroMem (Ascii, sizeof (Ascii));\r
1309\r
1310 gST->ConOut->ClearScreen(gST->ConOut);\r
1311 return EFI_SUCCESS;\r
1312}\r
1313\r
1314/**\r
1315 Check if disk is locked, show popup window and ask for password if it is.\r
1316\r
1317 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1318 @param[in] Port The port number of attached ATA device.\r
1319 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1320 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1321\r
1322**/\r
1323VOID\r
1324HddPasswordRequestPassword (\r
1325 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1326 IN UINT16 Port,\r
1327 IN UINT16 PortMultiplierPort,\r
1328 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1329 )\r
1330{\r
1331 EFI_STATUS Status;\r
1332 CHAR16 PopUpString[100];\r
1333 ATA_IDENTIFY_DATA IdentifyData;\r
1334 EFI_INPUT_KEY Key;\r
1335 UINT16 RetryCount;\r
1336 CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];\r
1337\r
1338 RetryCount = 0;\r
1339\r
1340 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1341\r
1342 UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Unlock: %s", ConfigFormEntry->HddString);\r
1343\r
1344 //\r
1345 // Check the device security status.\r
1346 //\r
1347 if ((ConfigFormEntry->IfrData.SecurityStatus.Supported) &&\r
1348 (ConfigFormEntry->IfrData.SecurityStatus.Enabled)) {\r
9e2416ae
CM
1349\r
1350 //\r
1351 // Add PcdSkipHddPasswordPrompt to determin whether to skip password prompt.\r
1352 // Due to board design, device may not power off during system warm boot, which result in\r
1353 // security status remain unlocked status, hence we add device security status check here.\r
1354 //\r
1355 // If device is in the locked status, device keeps locked and system continues booting.\r
1356 // If device is in the unlocked status, system is forced shutdown for security concern.\r
1357 //\r
1358 if (PcdGetBool (PcdSkipHddPasswordPrompt)) {\r
1359 if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {\r
1360 return;\r
1361 } else {\r
1362 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
1363 }\r
1364 }\r
e8959f81
HW
1365 //\r
1366 // As soon as the HDD password is in enabled state, we pop up a window to unlock hdd\r
1367 // no matter it's really in locked or unlocked state.\r
1368 // This way forces user to enter password every time to provide best safety.\r
1369 //\r
1370 while (TRUE) {\r
1371 Status = PopupHddPasswordInputWindows (PopUpString, NULL, Password);\r
1372 if (!EFI_ERROR (Status)) {\r
1373 //\r
1374 // The HDD is in locked state, unlock it by user input.\r
1375 //\r
1376 if (!PasswordIsFullZero (Password)) {\r
1377 if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1378 Status = UnlockHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, Password);\r
1379 } else {\r
1380 //\r
1381 // Use saved HDD password variable to validate HDD password\r
1382 // when the device is at frozen state.\r
1383 //\r
1384 Status = ValidateHddPassword (ConfigFormEntry, Password);\r
1385 }\r
1386 } else {\r
1387 Status = EFI_INVALID_PARAMETER;\r
1388 }\r
1389 if (!EFI_ERROR (Status)) {\r
1390 CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);\r
1391 if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1392 SaveHddPasswordVariable (ConfigFormEntry, Password);\r
1393 }\r
1394 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1395 Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);\r
1396 ASSERT_EFI_ERROR (Status);\r
1397\r
1398 //\r
1399 // Check the device security status again.\r
1400 //\r
1401 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
1402 return;\r
1403 }\r
1404\r
1405 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1406\r
1407 if (EFI_ERROR (Status)) {\r
1408 RetryCount ++;\r
1409 if (RetryCount < MAX_HDD_PASSWORD_RETRY_COUNT) {\r
1410 do {\r
1411 CreatePopUp (\r
1412 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1413 &Key,\r
1414 L"Invalid password.",\r
1415 L"Press ENTER to retry",\r
1416 NULL\r
1417 );\r
1418 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1419 continue;\r
1420 } else {\r
1421 do {\r
1422 CreatePopUp (\r
1423 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1424 &Key,\r
1425 L"Hdd password retry count is expired. Please shutdown the machine.",\r
1426 L"Press ENTER to shutdown",\r
1427 NULL\r
1428 );\r
1429 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1430 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
1431 break;\r
1432 }\r
1433 }\r
1434 } else if (Status == EFI_ABORTED) {\r
1435 if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {\r
1436 //\r
1437 // Current device in the lock status and\r
1438 // User not input password and press ESC,\r
1439 // keep device in lock status and continue boot.\r
1440 //\r
1441 do {\r
1442 CreatePopUp (\r
1443 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1444 &Key,\r
1445 L"Press ENTER to skip the request and continue boot,",\r
1446 L"Press ESC to input password again",\r
1447 NULL\r
1448 );\r
1449 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1450\r
1451 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1452 gST->ConOut->ClearScreen(gST->ConOut);\r
1453 //\r
1454 // Keep lock and continue boot.\r
1455 //\r
1456 return;\r
1457 } else {\r
1458 //\r
1459 // Let user input password again.\r
1460 //\r
1461 continue;\r
1462 }\r
1463 } else {\r
1464 //\r
1465 // Current device in the unlock status and\r
1466 // User not input password and press ESC,\r
1467 // Shutdown the device.\r
1468 //\r
1469 do {\r
1470 CreatePopUp (\r
1471 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1472 &Key,\r
1473 L"Press ENTER to shutdown, Press ESC to input password again",\r
1474 NULL\r
1475 );\r
1476 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1477\r
1478 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1479 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
1480 } else {\r
1481 //\r
1482 // Let user input password again.\r
1483 //\r
1484 continue;\r
1485 }\r
1486 }\r
1487 }\r
1488 }\r
1489 }\r
1490}\r
1491\r
1492/**\r
1493 Process Set User Pwd HDD password request.\r
1494\r
1495 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1496 @param[in] Port The port number of attached ATA device.\r
1497 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1498 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1499\r
1500**/\r
1501VOID\r
1502ProcessHddPasswordRequestSetUserPwd (\r
1503 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1504 IN UINT16 Port,\r
1505 IN UINT16 PortMultiplierPort,\r
1506 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1507 )\r
1508{\r
1509 EFI_STATUS Status;\r
1510 CHAR16 PopUpString[100];\r
1511 ATA_IDENTIFY_DATA IdentifyData;\r
1512 EFI_INPUT_KEY Key;\r
1513 UINT16 RetryCount;\r
1514 CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];\r
1515 CHAR8 PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];\r
1516\r
1517 RetryCount = 0;\r
1518\r
1519 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1520\r
1521 if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1522 DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));\r
1523 return;\r
1524 }\r
1525\r
1526 if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {\r
1527 DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));\r
1528 return;\r
1529 }\r
1530\r
1531 UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set User Pwd: %s", ConfigFormEntry->HddString);\r
1532\r
1533 //\r
1534 // Check the device security status.\r
1535 //\r
1536 if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {\r
1537 while (TRUE) {\r
1538 Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);\r
1539 if (!EFI_ERROR (Status)) {\r
1540 Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);\r
1541 if (!EFI_ERROR (Status)) {\r
1542 if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {\r
1543 if (!PasswordIsFullZero (Password)) {\r
1544 Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, 1, 0, Password);\r
1545 } else {\r
1546 if (ConfigFormEntry->IfrData.SecurityStatus.Enabled) {\r
1547 Status = DisableHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, ConfigFormEntry->Password);\r
1548 } else {\r
1549 Status = EFI_INVALID_PARAMETER;\r
1550 }\r
1551 }\r
1552 if (!EFI_ERROR (Status)) {\r
1553 CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);\r
1554 SaveHddPasswordVariable (ConfigFormEntry, Password);\r
1555 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1556 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1557 Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);\r
1558 ASSERT_EFI_ERROR (Status);\r
1559\r
1560 //\r
1561 // Check the device security status again.\r
1562 //\r
1563 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
1564 return;\r
1565 } else {\r
1566 do {\r
1567 CreatePopUp (\r
1568 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1569 &Key,\r
1570 L"Set/Disable User Pwd failed or invalid password.",\r
1571 L"Press ENTER to retry",\r
1572 NULL\r
1573 );\r
1574 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1575 }\r
1576 } else {\r
1577 do {\r
1578 CreatePopUp (\r
1579 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1580 &Key,\r
1581 L"Passwords are not the same.",\r
1582 L"Press ENTER to retry",\r
1583 NULL\r
1584 );\r
1585 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1586 Status = EFI_INVALID_PARAMETER;\r
1587 }\r
1588 }\r
1589\r
1590 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1591 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1592\r
1593 if (EFI_ERROR (Status)) {\r
1594 RetryCount ++;\r
1595 if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {\r
1596 do {\r
1597 CreatePopUp (\r
1598 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1599 &Key,\r
1600 L"Hdd password retry count is expired.",\r
1601 L"Press ENTER to skip the request and continue boot",\r
1602 NULL\r
1603 );\r
1604 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1605 gST->ConOut->ClearScreen(gST->ConOut);\r
1606 return;\r
1607 }\r
1608 }\r
1609 } else if (Status == EFI_ABORTED) {\r
1610 do {\r
1611 CreatePopUp (\r
1612 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1613 &Key,\r
1614 L"Press ENTER to skip the request and continue boot,",\r
1615 L"Press ESC to input password again",\r
1616 NULL\r
1617 );\r
1618 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1619\r
1620 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1621 gST->ConOut->ClearScreen(gST->ConOut);\r
1622 return;\r
1623 } else {\r
1624 //\r
1625 // Let user input password again.\r
1626 //\r
1627 continue;\r
1628 }\r
1629 }\r
1630 }\r
1631 }\r
1632}\r
1633\r
1634/**\r
1635 Process Set Master Pwd HDD password request.\r
1636\r
1637 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1638 @param[in] Port The port number of attached ATA device.\r
1639 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1640 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1641\r
1642**/\r
1643VOID\r
1644ProcessHddPasswordRequestSetMasterPwd (\r
1645 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1646 IN UINT16 Port,\r
1647 IN UINT16 PortMultiplierPort,\r
1648 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1649 )\r
1650{\r
1651 EFI_STATUS Status;\r
1652 CHAR16 PopUpString[100];\r
1653 EFI_INPUT_KEY Key;\r
1654 UINT16 RetryCount;\r
1655 CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];\r
1656 CHAR8 PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];\r
1657\r
1658 RetryCount = 0;\r
1659\r
1660 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1661\r
1662 if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {\r
1663 DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));\r
1664 return;\r
1665 }\r
1666\r
1667 if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {\r
1668 DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));\r
1669 return;\r
1670 }\r
1671\r
1672 UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set Master Pwd: %s", ConfigFormEntry->HddString);\r
1673\r
1674 //\r
1675 // Check the device security status.\r
1676 //\r
1677 if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {\r
1678 while (TRUE) {\r
1679 Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);\r
1680 if (!EFI_ERROR (Status)) {\r
1681 Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);\r
1682 if (!EFI_ERROR (Status)) {\r
1683 if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {\r
1684 if (!PasswordIsFullZero (Password)) {\r
1685 Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 1, 1, 1, Password);\r
1686 } else {\r
1687 Status = EFI_INVALID_PARAMETER;\r
1688 }\r
1689 if (!EFI_ERROR (Status)) {\r
1690 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1691 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1692 return;\r
1693 } else {\r
1694 do {\r
1695 CreatePopUp (\r
1696 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1697 &Key,\r
1698 L"Set Master Pwd failed or invalid password.",\r
1699 L"Press ENTER to retry",\r
1700 NULL\r
1701 );\r
1702 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1703 }\r
1704 } else {\r
1705 do {\r
1706 CreatePopUp (\r
1707 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1708 &Key,\r
1709 L"Passwords are not the same.",\r
1710 L"Press ENTER to retry",\r
1711 NULL\r
1712 );\r
1713 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1714 Status = EFI_INVALID_PARAMETER;\r
1715 }\r
1716 }\r
1717\r
1718 ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);\r
1719 ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);\r
1720\r
1721 if (EFI_ERROR (Status)) {\r
1722 RetryCount ++;\r
1723 if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {\r
1724 do {\r
1725 CreatePopUp (\r
1726 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1727 &Key,\r
1728 L"Hdd password retry count is expired.",\r
1729 L"Press ENTER to skip the request and continue boot",\r
1730 NULL\r
1731 );\r
1732 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1733 gST->ConOut->ClearScreen(gST->ConOut);\r
1734 return;\r
1735 }\r
1736 }\r
1737 } else if (Status == EFI_ABORTED) {\r
1738 do {\r
1739 CreatePopUp (\r
1740 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1741 &Key,\r
1742 L"Press ENTER to skip the request and continue boot,",\r
1743 L"Press ESC to input password again",\r
1744 NULL\r
1745 );\r
1746 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1747\r
1748 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1749 gST->ConOut->ClearScreen(gST->ConOut);\r
1750 return;\r
1751 } else {\r
1752 //\r
1753 // Let user input password again.\r
1754 //\r
1755 continue;\r
1756 }\r
1757 }\r
1758 }\r
1759 }\r
1760}\r
1761\r
1762/**\r
1763 Process HDD password request.\r
1764\r
1765 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
1766 @param[in] Port The port number of attached ATA device.\r
1767 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
1768 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1769\r
1770**/\r
1771VOID\r
1772ProcessHddPasswordRequest (\r
1773 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
1774 IN UINT16 Port,\r
1775 IN UINT16 PortMultiplierPort,\r
1776 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1777 )\r
1778{\r
1779 EFI_STATUS Status;\r
1780 HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;\r
1781 HDD_PASSWORD_REQUEST_VARIABLE *Variable;\r
1782 UINTN VariableSize;\r
1783\r
1784 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
1785\r
1786 if (mHddPasswordRequestVariable == NULL) {\r
1787 Status = GetVariable2 (\r
1788 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1789 &mHddPasswordVendorGuid,\r
1790 (VOID **) &Variable,\r
1791 &VariableSize\r
1792 );\r
1793 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
1794 return;\r
1795 }\r
1796 mHddPasswordRequestVariable = Variable;\r
1797 mHddPasswordRequestVariableSize = VariableSize;\r
1798\r
1799 //\r
1800 // Delete the HDD password request variable.\r
1801 //\r
1802 Status = gRT->SetVariable (\r
1803 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1804 &mHddPasswordVendorGuid,\r
1805 0,\r
1806 0,\r
1807 NULL\r
1808 );\r
1809 ASSERT_EFI_ERROR (Status);\r
1810 } else {\r
1811 Variable = mHddPasswordRequestVariable;\r
1812 VariableSize = mHddPasswordRequestVariableSize;\r
1813 }\r
1814\r
1815 //\r
1816 // Process the HDD password requests.\r
1817 //\r
1818 TempVariable = Variable;\r
1819 while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {\r
1820 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
1821 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
1822 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
1823 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
1824 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
1825 //\r
1826 // Found the node for the HDD password device.\r
1827 //\r
1828 if (TempVariable->Request.UserPassword != 0) {\r
1829 ProcessHddPasswordRequestSetUserPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
1830 }\r
1831 if (TempVariable->Request.MasterPassword != 0) {\r
1832 ProcessHddPasswordRequestSetMasterPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
1833 }\r
1834\r
1835 break;\r
1836 }\r
1837\r
1838 VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1839 TempVariable += 1;\r
1840 }\r
1841\r
1842 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
1843}\r
1844\r
1845/**\r
1846 Get saved HDD password request.\r
1847\r
1848 @param[in, out] ConfigFormEntry The HDD Password configuration form entry.\r
1849\r
1850**/\r
1851VOID\r
1852GetSavedHddPasswordRequest (\r
1853 IN OUT HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1854 )\r
1855{\r
1856 EFI_STATUS Status;\r
1857 HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;\r
1858 HDD_PASSWORD_REQUEST_VARIABLE *Variable;\r
1859 UINTN VariableSize;\r
1860\r
1861 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
1862\r
1863 Variable = NULL;\r
1864 VariableSize = 0;\r
1865\r
1866 Status = GetVariable2 (\r
1867 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1868 &mHddPasswordVendorGuid,\r
1869 (VOID **) &Variable,\r
1870 &VariableSize\r
1871 );\r
1872 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
1873 return;\r
1874 }\r
1875\r
1876 TempVariable = Variable;\r
1877 while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {\r
1878 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
1879 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
1880 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
1881 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
1882 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
1883 //\r
1884 // Found the node for the HDD password device.\r
1885 // Get the HDD password request.\r
1886 //\r
1887 CopyMem (&ConfigFormEntry->IfrData.Request, &TempVariable->Request, sizeof (HDD_PASSWORD_REQUEST));\r
1888 DEBUG ((\r
1889 DEBUG_INFO,\r
1890 "HddPasswordRequest got: 0x%x\n",\r
1891 ConfigFormEntry->IfrData.Request\r
1892 ));\r
1893 break;\r
1894 }\r
1895 VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1896 TempVariable += 1;\r
1897 }\r
1898\r
1899 FreePool (Variable);\r
1900\r
1901 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
1902}\r
1903\r
1904/**\r
1905 Save HDD password request.\r
1906\r
1907 @param[in] ConfigFormEntry The HDD Password configuration form entry.\r
1908\r
1909**/\r
1910VOID\r
1911SaveHddPasswordRequest (\r
1912 IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry\r
1913 )\r
1914{\r
1915 EFI_STATUS Status;\r
1916 HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;\r
1917 UINTN TempVariableSize;\r
1918 HDD_PASSWORD_REQUEST_VARIABLE *Variable;\r
1919 UINTN VariableSize;\r
1920 HDD_PASSWORD_REQUEST_VARIABLE *NewVariable;\r
1921 UINTN NewVariableSize;\r
1922\r
1923 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
1924\r
1925 DEBUG ((\r
1926 DEBUG_INFO,\r
1927 "HddPasswordRequest to save: 0x%x\n",\r
1928 ConfigFormEntry->IfrData.Request\r
1929 ));\r
1930\r
1931 Variable = NULL;\r
1932 VariableSize = 0;\r
1933 NewVariable = NULL;\r
1934 NewVariableSize = 0;\r
1935\r
1936 Status = GetVariable2 (\r
1937 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1938 &mHddPasswordVendorGuid,\r
1939 (VOID **) &Variable,\r
1940 &VariableSize\r
1941 );\r
1942 if (!EFI_ERROR (Status) && (Variable != NULL)) {\r
1943 TempVariable = Variable;\r
1944 TempVariableSize = VariableSize;\r
1945 while (TempVariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {\r
1946 if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&\r
1947 (TempVariable->Device.Device == ConfigFormEntry->Device) &&\r
1948 (TempVariable->Device.Function == ConfigFormEntry->Function) &&\r
1949 (TempVariable->Device.Port == ConfigFormEntry->Port) &&\r
1950 (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {\r
1951 //\r
1952 // Found the node for the HDD password device.\r
1953 // Update the HDD password request.\r
1954 //\r
1955 CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));\r
1956 NewVariable = Variable;\r
1957 NewVariableSize = VariableSize;\r
1958 break;\r
1959 }\r
1960 TempVariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1961 TempVariable += 1;\r
1962 }\r
1963 if (NewVariable == NULL) {\r
1964 //\r
1965 // The node for the HDD password device is not found.\r
1966 // Create node for the HDD password device.\r
1967 //\r
1968 NewVariableSize = VariableSize + sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1969 NewVariable = AllocateZeroPool (NewVariableSize);\r
1970 ASSERT (NewVariable != NULL);\r
1971 CopyMem (NewVariable, Variable, VariableSize);\r
1972 TempVariable = (HDD_PASSWORD_REQUEST_VARIABLE *) ((UINTN) NewVariable + VariableSize);\r
1973 TempVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
1974 TempVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
1975 TempVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
1976 TempVariable->Device.Port = ConfigFormEntry->Port;\r
1977 TempVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
1978 CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));\r
1979 }\r
1980 } else {\r
1981 NewVariableSize = sizeof (HDD_PASSWORD_REQUEST_VARIABLE);\r
1982 NewVariable = AllocateZeroPool (NewVariableSize);\r
1983 ASSERT (NewVariable != NULL);\r
1984 NewVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;\r
1985 NewVariable->Device.Device = (UINT8) ConfigFormEntry->Device;\r
1986 NewVariable->Device.Function = (UINT8) ConfigFormEntry->Function;\r
1987 NewVariable->Device.Port = ConfigFormEntry->Port;\r
1988 NewVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;\r
1989 CopyMem (&NewVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));\r
1990 }\r
1991 Status = gRT->SetVariable (\r
1992 HDD_PASSWORD_REQUEST_VARIABLE_NAME,\r
1993 &mHddPasswordVendorGuid,\r
1994 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
1995 NewVariableSize,\r
1996 NewVariable\r
1997 );\r
1998 if (EFI_ERROR (Status)) {\r
1999 DEBUG ((DEBUG_INFO, "HddPasswordRequest variable set failed (%r)\n", Status));\r
2000 }\r
2001 if (NewVariable != Variable) {\r
2002 FreePool (NewVariable);\r
2003 }\r
2004 if (Variable != NULL) {\r
2005 FreePool (Variable);\r
2006 }\r
2007\r
2008 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
2009}\r
2010\r
2011/**\r
d6b926e7 2012 Get the HDD Password configuration form entry by the index of the goto opcode activated.\r
e8959f81 2013\r
d6b926e7 2014 @param[in] Index The 0-based index of the goto opcode activated.\r
e8959f81
HW
2015\r
2016 @return The HDD Password configuration form entry found.\r
2017**/\r
2018HDD_PASSWORD_CONFIG_FORM_ENTRY *\r
2019HddPasswordGetConfigFormEntryByIndex (\r
2020 IN UINT32 Index\r
2021 )\r
2022{\r
2023 LIST_ENTRY *Entry;\r
2024 UINT32 CurrentIndex;\r
2025 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
2026\r
2027 CurrentIndex = 0;\r
2028 ConfigFormEntry = NULL;\r
2029\r
3571e136 2030 BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
e8959f81
HW
2031 if (CurrentIndex == Index) {\r
2032 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
2033 break;\r
2034 }\r
2035\r
2036 CurrentIndex++;\r
2037 }\r
2038\r
2039 return ConfigFormEntry;\r
2040}\r
2041\r
2042/**\r
2043 This function allows the caller to request the current\r
2044 configuration for one or more named elements. The resulting\r
2045 string is in <ConfigAltResp> format. Any and all alternative\r
2046 configuration strings shall also be appended to the end of the\r
2047 current configuration string. If they are, they must appear\r
2048 after the current configuration. They must contain the same\r
2049 routing (GUID, NAME, PATH) as the current configuration string.\r
2050 They must have an additional description indicating the type of\r
2051 alternative configuration the string represents,\r
2052 "ALTCFG=<StringToken>". That <StringToken> (when\r
2053 converted from Hex UNICODE to binary) is a reference to a\r
2054 string in the associated string pack.\r
2055\r
2056 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2057 @param[in] Request A null-terminated Unicode string in\r
2058 <ConfigRequest> format. Note that this\r
2059 includes the routing information as well as\r
2060 the configurable name / value pairs. It is\r
2061 invalid for this string to be in\r
2062 <MultiConfigRequest> format.\r
2063 @param[out] Progress On return, points to a character in the\r
2064 Request string. Points to the string's null\r
2065 terminator if request was successful. Points\r
2066 to the most recent "&" before the first\r
2067 failing name / value pair (or the beginning\r
2068 of the string if the failure is in the first\r
2069 name / value pair) if the request was not\r
2070 successful.\r
2071 @param[out] Results A null-terminated Unicode string in\r
2072 <ConfigAltResp> format which has all values\r
2073 filled in for the names in the Request string.\r
2074 String to be allocated by the called function.\r
2075\r
2076 @retval EFI_SUCCESS The Results string is filled with the\r
2077 values corresponding to all requested\r
2078 names.\r
2079 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
2080 parts of the results that must be\r
2081 stored awaiting possible future\r
2082 protocols.\r
2083 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
2084 for the Request parameter\r
2085 would result in this type of\r
2086 error. In this case, the\r
2087 Progress parameter would be\r
2088 set to NULL.\r
2089 @retval EFI_NOT_FOUND Routing data doesn't match any\r
2090 known driver. Progress set to the\r
2091 first character in the routing header.\r
2092 Note: There is no requirement that the\r
2093 driver validate the routing data. It\r
2094 must skip the <ConfigHdr> in order to\r
2095 process the names.\r
2096 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
2097 to most recent & before the\r
2098 error or the beginning of the\r
2099 string.\r
2100 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
2101 to the & before the name in\r
2102 question.Currently not implemented.\r
2103**/\r
2104EFI_STATUS\r
2105EFIAPI\r
2106HddPasswordFormExtractConfig (\r
2107 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2108 IN CONST EFI_STRING Request,\r
2109 OUT EFI_STRING *Progress,\r
2110 OUT EFI_STRING *Results\r
2111 )\r
2112{\r
2113 EFI_STATUS Status;\r
2114 UINTN BufferSize;\r
2115 HDD_PASSWORD_CONFIG *IfrData;\r
2116 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2117 EFI_STRING ConfigRequestHdr;\r
2118 EFI_STRING ConfigRequest;\r
2119 BOOLEAN AllocatedRequest;\r
2120 UINTN Size;\r
2121\r
2122 if (Progress == NULL || Results == NULL) {\r
2123 return EFI_INVALID_PARAMETER;\r
2124 }\r
2125\r
2126 *Progress = Request;\r
2127 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {\r
2128 return EFI_NOT_FOUND;\r
2129 }\r
2130\r
2131 ConfigRequestHdr = NULL;\r
2132 ConfigRequest = NULL;\r
2133 AllocatedRequest = FALSE;\r
2134 Size = 0;\r
2135\r
2136 Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);\r
2137 IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));\r
2138 ASSERT (IfrData != NULL);\r
2139 if (Private->Current != NULL) {\r
2140 CopyMem (IfrData, &Private->Current->IfrData, sizeof (HDD_PASSWORD_CONFIG));\r
2141 }\r
2142\r
2143 //\r
2144 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
2145 //\r
2146 BufferSize = sizeof (HDD_PASSWORD_CONFIG);\r
2147 ConfigRequest = Request;\r
2148 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
2149 //\r
2150 // Request has no request element, construct full request string.\r
2151 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
2152 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
2153 //\r
2154 ConfigRequestHdr = HiiConstructConfigHdr (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, Private->DriverHandle);\r
2155 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
2156 ConfigRequest = AllocateZeroPool (Size);\r
2157 ASSERT (ConfigRequest != NULL);\r
2158 AllocatedRequest = TRUE;\r
2159 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
2160 FreePool (ConfigRequestHdr);\r
2161 }\r
2162 Status = gHiiConfigRouting->BlockToConfig (\r
2163 gHiiConfigRouting,\r
2164 ConfigRequest,\r
2165 (UINT8 *) IfrData,\r
2166 BufferSize,\r
2167 Results,\r
2168 Progress\r
2169 );\r
2170 FreePool (IfrData);\r
2171 //\r
2172 // Free the allocated config request string.\r
2173 //\r
2174 if (AllocatedRequest) {\r
2175 FreePool (ConfigRequest);\r
2176 ConfigRequest = NULL;\r
2177 }\r
2178\r
2179 //\r
2180 // Set Progress string to the original request string.\r
2181 //\r
2182 if (Request == NULL) {\r
2183 *Progress = NULL;\r
2184 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
2185 *Progress = Request + StrLen (Request);\r
2186 }\r
2187\r
2188 return Status;\r
2189}\r
2190\r
2191/**\r
2192 This function applies changes in a driver's configuration.\r
2193 Input is a Configuration, which has the routing data for this\r
2194 driver followed by name / value configuration pairs. The driver\r
2195 must apply those pairs to its configurable storage. If the\r
2196 driver's configuration is stored in a linear block of data\r
2197 and the driver's name / value pairs are in <BlockConfig>\r
2198 format, it may use the ConfigToBlock helper function (above) to\r
2199 simplify the job. Currently not implemented.\r
2200\r
2201 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2202 @param[in] Configuration A null-terminated Unicode string in\r
2203 <ConfigString> format.\r
2204 @param[out] Progress A pointer to a string filled in with the\r
2205 offset of the most recent '&' before the\r
2206 first failing name / value pair (or the\r
2207 beginn ing of the string if the failure\r
2208 is in the first name / value pair) or\r
2209 the terminating NULL if all was\r
2210 successful.\r
2211\r
2212 @retval EFI_SUCCESS The results have been distributed or are\r
2213 awaiting distribution.\r
2214 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
2215 parts of the results that must be\r
2216 stored awaiting possible future\r
2217 protocols.\r
2218 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
2219 Results parameter would result\r
2220 in this type of error.\r
2221 @retval EFI_NOT_FOUND Target for the specified routing data\r
2222 was not found.\r
2223**/\r
2224EFI_STATUS\r
2225EFIAPI\r
2226HddPasswordFormRouteConfig (\r
2227 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2228 IN CONST EFI_STRING Configuration,\r
2229 OUT EFI_STRING *Progress\r
2230 )\r
2231{\r
2232 if (Configuration == NULL || Progress == NULL) {\r
2233 return EFI_INVALID_PARAMETER;\r
2234 }\r
2235\r
2236 //\r
2237 // Check routing data in <ConfigHdr>.\r
2238 // Note: if only one Storage is used, then this checking could be skipped.\r
2239 //\r
2240 if (!HiiIsConfigHdrMatch (Configuration, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {\r
2241 *Progress = Configuration;\r
2242 return EFI_NOT_FOUND;\r
2243 }\r
2244\r
2245 *Progress = Configuration + StrLen (Configuration);\r
2246 return EFI_SUCCESS;\r
2247}\r
2248\r
2249/**\r
2250 This function is called to provide results data to the driver.\r
2251 This data consists of a unique key that is used to identify\r
2252 which data is either being passed back or being asked for.\r
2253\r
2254 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
2255 @param[in] Action Specifies the type of action taken by the browser.\r
2256 @param[in] QuestionId A unique value which is sent to the original\r
2257 exporting driver so that it can identify the type\r
2258 of data to expect. The format of the data tends to\r
2259 vary based on the opcode that enerated the callback.\r
2260 @param[in] Type The type of value for the question.\r
2261 @param[in] Value A pointer to the data being sent to the original\r
2262 exporting driver.\r
2263 @param[out] ActionRequest On return, points to the action requested by the\r
2264 callback function.\r
2265\r
2266 @retval EFI_SUCCESS The callback successfully handled the action.\r
2267 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
2268 variable and its data.\r
2269 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
2270 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
2271 callback.Currently not implemented.\r
2272 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.\r
2273 @retval Others Other errors as indicated.\r
2274**/\r
2275EFI_STATUS\r
2276EFIAPI\r
2277HddPasswordFormCallback (\r
2278 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
2279 IN EFI_BROWSER_ACTION Action,\r
2280 IN EFI_QUESTION_ID QuestionId,\r
2281 IN UINT8 Type,\r
2282 IN EFI_IFR_TYPE_VALUE *Value,\r
2283 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
2284 )\r
2285{\r
2286 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2287 EFI_STRING_ID DeviceFormTitleToken;\r
2288 HDD_PASSWORD_CONFIG *IfrData;\r
2289 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
2290\r
2291 if (ActionRequest != NULL) {\r
2292 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;\r
2293 } else {\r
2294 return EFI_INVALID_PARAMETER;\r
2295 }\r
2296\r
2297 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {\r
2298 //\r
2299 // Do nothing for other UEFI Action. Only do call back when data is changing or changed.\r
2300 //\r
2301 return EFI_UNSUPPORTED;\r
2302 }\r
2303\r
2304 Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);\r
2305\r
2306 //\r
2307 // Retrive data from Browser\r
2308 //\r
2309 IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));\r
2310 ASSERT (IfrData != NULL);\r
2311 if (!HiiGetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData)) {\r
2312 FreePool (IfrData);\r
2313 return EFI_NOT_FOUND;\r
2314 }\r
2315\r
2316 switch (QuestionId) {\r
2317 case KEY_HDD_USER_PASSWORD:\r
2318 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2319 DEBUG ((DEBUG_INFO, "KEY_HDD_USER_PASSWORD\n"));\r
2320 ConfigFormEntry = Private->Current;\r
2321 ConfigFormEntry->IfrData.Request.UserPassword = Value->b;\r
2322 SaveHddPasswordRequest (ConfigFormEntry);\r
2323 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2324 }\r
2325 break;\r
2326 case KEY_HDD_MASTER_PASSWORD:\r
2327 if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
2328 DEBUG ((DEBUG_INFO, "KEY_HDD_MASTER_PASSWORD\n"));\r
2329 ConfigFormEntry = Private->Current;\r
2330 ConfigFormEntry->IfrData.Request.MasterPassword = Value->b;\r
2331 SaveHddPasswordRequest (ConfigFormEntry);\r
2332 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
2333 }\r
2334 break;\r
2335\r
2336 default:\r
2337 if ((QuestionId >= KEY_HDD_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfHddDevices + KEY_HDD_DEVICE_ENTRY_BASE))) {\r
2338 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
2339 //\r
2340 // In case goto the device configuration form, update the device form title.\r
2341 //\r
2342 ConfigFormEntry = HddPasswordGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_HDD_DEVICE_ENTRY_BASE));\r
2343 ASSERT (ConfigFormEntry != NULL);\r
2344\r
2345 DeviceFormTitleToken = (EFI_STRING_ID) STR_HDD_SECURITY_HD;\r
2346 HiiSetString (Private->HiiHandle, DeviceFormTitleToken, ConfigFormEntry->HddString, NULL);\r
2347\r
2348 Private->Current = ConfigFormEntry;\r
2349 CopyMem (IfrData, &ConfigFormEntry->IfrData, sizeof (HDD_PASSWORD_CONFIG));\r
2350 }\r
2351 }\r
2352\r
2353 break;\r
2354 }\r
2355\r
2356 //\r
2357 // Pass changed uncommitted data back to Form Browser\r
2358 //\r
2359 HiiSetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData, NULL);\r
2360\r
2361 FreePool (IfrData);\r
2362 return EFI_SUCCESS;\r
2363}\r
2364\r
2365/**\r
2366 Updates the HDD Password configuration form to add an entry for the attached\r
2367 ata harddisk device specified by the Controller.\r
2368\r
2369 @param[in] HiiHandle The HII Handle associated with the registered package list.\r
2370 @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.\r
2371 @param[in] PciIo Pointer to PCI_IO instance.\r
2372 @param[in] Controller The controller handle of the attached ata controller.\r
2373 @param[in] Bus The bus number of ATA controller.\r
2374 @param[in] Device The device number of ATA controller.\r
2375 @param[in] Function The function number of ATA controller.\r
2376 @param[in] Port The port number of attached ATA device.\r
2377 @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.\r
2378\r
2379 @retval EFI_SUCCESS The Hdd Password configuration form is updated.\r
2380 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
2381 @retval Others Other errors as indicated.\r
2382\r
2383**/\r
2384EFI_STATUS\r
2385HddPasswordConfigUpdateForm (\r
2386 IN EFI_HII_HANDLE HiiHandle,\r
2387 IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,\r
2388 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
2389 IN EFI_HANDLE Controller,\r
2390 IN UINTN Bus,\r
2391 IN UINTN Device,\r
2392 IN UINTN Function,\r
2393 IN UINT16 Port,\r
2394 IN UINT16 PortMultiplierPort\r
2395 )\r
2396{\r
2397 LIST_ENTRY *Entry;\r
2398 HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
2399 BOOLEAN EntryExisted;\r
2400 EFI_STATUS Status;\r
2401 VOID *StartOpCodeHandle;\r
2402 VOID *EndOpCodeHandle;\r
2403 EFI_IFR_GUID_LABEL *StartLabel;\r
2404 EFI_IFR_GUID_LABEL *EndLabel;\r
2405 CHAR16 HddString[40];\r
2406 ATA_IDENTIFY_DATA IdentifyData;\r
2407 EFI_DEVICE_PATH_PROTOCOL *AtaDeviceNode;\r
2408\r
2409 ConfigFormEntry = NULL;\r
2410 EntryExisted = FALSE;\r
2411\r
3571e136 2412 BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
e8959f81
HW
2413 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
2414\r
2415 if ((ConfigFormEntry->Bus == Bus) &&\r
2416 (ConfigFormEntry->Device == Device) &&\r
2417 (ConfigFormEntry->Function == Function) &&\r
2418 (ConfigFormEntry->Port == Port) &&\r
2419 (ConfigFormEntry->PortMultiplierPort == PortMultiplierPort)) {\r
2420 EntryExisted = TRUE;\r
2421 break;\r
2422 }\r
2423 }\r
2424\r
2425 if (!EntryExisted) {\r
2426 //\r
2427 // Add a new form.\r
2428 //\r
2429 ConfigFormEntry = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG_FORM_ENTRY));\r
2430 if (ConfigFormEntry == NULL) {\r
2431 return EFI_OUT_OF_RESOURCES;\r
2432 }\r
2433\r
2434 InitializeListHead (&ConfigFormEntry->Link);\r
2435 ConfigFormEntry->Controller = Controller;\r
2436 ConfigFormEntry->Bus = Bus;\r
2437 ConfigFormEntry->Device = Device;\r
2438 ConfigFormEntry->Function = Function;\r
2439 ConfigFormEntry->Port = Port;\r
2440 ConfigFormEntry->PortMultiplierPort = PortMultiplierPort;\r
2441 ConfigFormEntry->AtaPassThru = AtaPassThru;\r
2442\r
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));\r
2444\r
2445 //\r
2446 // Construct the device path for the HDD password device\r
2447 //\r
2448 Status = AtaPassThru->BuildDevicePath (\r
2449 AtaPassThru,\r
2450 Port,\r
2451 PortMultiplierPort,\r
2452 &AtaDeviceNode\r
2453 );\r
2454 if (EFI_ERROR (Status)) {\r
2455 return Status;\r
2456 }\r
2457 ConfigFormEntry->DevicePath = AppendDevicePathNode (DevicePathFromHandle (Controller), AtaDeviceNode);\r
2458 FreePool (AtaDeviceNode);\r
2459 if (ConfigFormEntry->DevicePath == NULL) {\r
2460 return EFI_OUT_OF_RESOURCES;\r
2461 }\r
2462\r
2463 //\r
2464 // Get attached harddisk model number\r
2465 //\r
2466 Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);\r
2467 ASSERT_EFI_ERROR (Status);\r
2468 if (EFI_ERROR (Status)) {\r
2469 return Status;\r
2470 }\r
2471 GetHddDeviceModelNumber (&IdentifyData, HddString);\r
2472 //\r
2473 // Compose the HDD title string and help string of this port and create a new EFI_STRING_ID.\r
2474 //\r
2475 UnicodeSPrint (ConfigFormEntry->HddString, sizeof (ConfigFormEntry->HddString), L"HDD %d:%s", mNumberOfHddDevices, HddString);\r
2476 ConfigFormEntry->TitleToken = HiiSetString (HiiHandle, 0, ConfigFormEntry->HddString, NULL);\r
2477 ConfigFormEntry->TitleHelpToken = HiiSetString (HiiHandle, 0, L"Request to set HDD Password", NULL);\r
2478\r
2479 GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);\r
2480\r
2481 InsertTailList (&mHddPasswordConfigFormList, &ConfigFormEntry->Link);\r
2482\r
2483 //\r
2484 // Init OpCode Handle\r
2485 //\r
2486 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2487 ASSERT (StartOpCodeHandle != NULL);\r
2488\r
2489 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
2490 ASSERT (EndOpCodeHandle != NULL);\r
2491\r
2492 //\r
2493 // Create Hii Extend Label OpCode as the start opcode\r
2494 //\r
2495 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
2496 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2497 StartLabel->Number = HDD_DEVICE_ENTRY_LABEL;\r
2498\r
2499 //\r
2500 // Create Hii Extend Label OpCode as the end opcode\r
2501 //\r
2502 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
2503 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
2504 EndLabel->Number = HDD_DEVICE_LABEL_END;\r
2505\r
2506 mNumberOfHddDevices = 0;\r
3571e136 2507 BASE_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {\r
e8959f81
HW
2508 ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);\r
2509\r
2510 HiiCreateGotoOpCode (\r
2511 StartOpCodeHandle, // Container for dynamic created opcodes\r
2512 FORMID_HDD_DEVICE_FORM, // Target Form ID\r
2513 ConfigFormEntry->TitleToken, // Prompt text\r
2514 ConfigFormEntry->TitleHelpToken, // Help text\r
2515 EFI_IFR_FLAG_CALLBACK, // Question flag\r
2516 (UINT16) (KEY_HDD_DEVICE_ENTRY_BASE + mNumberOfHddDevices) // Question ID\r
2517 );\r
2518\r
2519 mNumberOfHddDevices++;\r
2520 }\r
2521\r
2522 HiiUpdateForm (\r
2523 HiiHandle,\r
2524 &mHddPasswordVendorGuid,\r
2525 FORMID_HDD_MAIN_FORM,\r
2526 StartOpCodeHandle,\r
2527 EndOpCodeHandle\r
2528 );\r
2529\r
2530 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
2531 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
2532\r
2533 //\r
2534 // Check if device is locked and prompt for password.\r
2535 //\r
2536 HddPasswordRequestPassword (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
2537\r
2538 //\r
2539 // Process HDD password request from last boot.\r
2540 //\r
2541 ProcessHddPasswordRequest (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);\r
2542 }\r
2543\r
2544 return EFI_SUCCESS;\r
2545}\r
2546\r
2547/**\r
2548 Ata Pass Thru Protocol notification event handler.\r
2549\r
2550 Check attached harddisk status to see if it's locked. If yes, then pop up a password windows to require user input.\r
2551 It also registers a form for user configuration on Hdd password configuration.\r
2552\r
2553 @param[in] Event Event whose notification function is being invoked.\r
2554 @param[in] Context Pointer to the notification function's context.\r
2555\r
2556**/\r
2557VOID\r
2558EFIAPI\r
2559HddPasswordNotificationEvent (\r
2560 IN EFI_EVENT Event,\r
2561 IN VOID *Context\r
2562 )\r
2563{\r
2564 EFI_STATUS Status;\r
2565 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2566 EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;\r
2567 UINT16 Port;\r
2568 UINT16 PortMultiplierPort;\r
2569 EFI_HANDLE Controller;\r
2570 EFI_HANDLE *HandleBuffer;\r
2571 UINTN HandleCount;\r
2572 UINTN Index;\r
2573 EFI_PCI_IO_PROTOCOL *PciIo;\r
2574 UINTN SegNum;\r
2575 UINTN BusNum;\r
2576 UINTN DevNum;\r
2577 UINTN FuncNum;\r
2578\r
2579 if (mHddPasswordEndOfDxe) {\r
2580 gBS->CloseEvent (Event);\r
2581 return;\r
2582 }\r
2583\r
2584 Private = (HDD_PASSWORD_DXE_PRIVATE_DATA *)Context;\r
2585\r
2586 //\r
2587 // Locate all handles of AtaPassThru protocol\r
2588 //\r
2589 Status = gBS->LocateHandleBuffer (\r
2590 ByProtocol,\r
2591 &gEfiAtaPassThruProtocolGuid,\r
2592 NULL,\r
2593 &HandleCount,\r
2594 &HandleBuffer\r
2595 );\r
2596 if (EFI_ERROR (Status)) {\r
2597 return ;\r
2598 }\r
2599\r
2600 //\r
2601 // Check attached hard disk status to see if it's locked\r
2602 //\r
2603 for (Index = 0; Index < HandleCount; Index += 1) {\r
2604 Controller = HandleBuffer[Index];\r
2605 Status = gBS->HandleProtocol (\r
2606 Controller,\r
2607 &gEfiAtaPassThruProtocolGuid,\r
2608 (VOID **) &AtaPassThru\r
2609 );\r
2610 if (EFI_ERROR (Status)) {\r
2611 break;\r
2612 }\r
2613\r
2614 //\r
2615 // Ignore those logical ATA_PASS_THRU instance.\r
2616 //\r
2617 if ((AtaPassThru->Mode->Attributes & EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL) == 0) {\r
2618 continue;\r
2619 }\r
2620\r
2621 Status = gBS->HandleProtocol (\r
2622 Controller,\r
2623 &gEfiPciIoProtocolGuid,\r
2624 (VOID **) &PciIo\r
2625 );\r
2626 ASSERT_EFI_ERROR (Status);\r
2627 if (EFI_ERROR (Status)) {\r
2628 break;\r
2629 }\r
2630\r
2631 Status = PciIo->GetLocation (\r
2632 PciIo,\r
2633 &SegNum,\r
2634 &BusNum,\r
2635 &DevNum,\r
2636 &FuncNum\r
2637 );\r
2638 ASSERT_EFI_ERROR (Status);\r
2639 if (EFI_ERROR (Status)) {\r
2640 break;\r
2641 }\r
2642\r
2643 //\r
2644 // Assume and only support Segment == 0.\r
2645 //\r
2646 ASSERT (SegNum == 0);\r
2647\r
2648 //\r
2649 // traverse all attached harddisk devices to update form and unlock it\r
2650 //\r
2651 Port = 0xFFFF;\r
2652\r
2653 while (TRUE) {\r
2654 Status = AtaPassThru->GetNextPort (AtaPassThru, &Port);\r
2655 if (EFI_ERROR (Status)) {\r
2656 //\r
2657 // We cannot find more legal port then we are done.\r
2658 //\r
2659 break;\r
2660 }\r
2661\r
2662 PortMultiplierPort = 0xFFFF;\r
2663 while (TRUE) {\r
2664 Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);\r
2665 if (EFI_ERROR (Status)) {\r
2666 //\r
2667 // We cannot find more legal port multiplier port number for ATA device\r
2668 // on the port, then we are done.\r
2669 //\r
2670 break;\r
2671 }\r
2672 //\r
2673 // Find out the attached harddisk devices.\r
2674 // Try to add a HDD Password configuration page for the attached devices.\r
2675 //\r
2676 gBS->RestoreTPL (TPL_APPLICATION);\r
2677 Status = HddPasswordConfigUpdateForm (Private->HiiHandle, AtaPassThru, PciIo, Controller, BusNum, DevNum, FuncNum, Port, PortMultiplierPort);\r
2678 gBS->RaiseTPL (TPL_CALLBACK);\r
2679 if (EFI_ERROR (Status)) {\r
2680 break;\r
2681 }\r
2682 }\r
2683 }\r
2684 }\r
2685\r
2686 FreePool (HandleBuffer);\r
2687 return ;\r
2688}\r
2689\r
2690/**\r
2691 Initialize the HDD Password configuration form.\r
2692\r
2693 @param[out] Instance Pointer to private instance.\r
2694\r
2695 @retval EFI_SUCCESS The HDD Password configuration form is initialized.\r
2696 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
2697 @retval Others Other errors as indicated.\r
2698**/\r
2699EFI_STATUS\r
2700HddPasswordConfigFormInit (\r
2701 OUT HDD_PASSWORD_DXE_PRIVATE_DATA **Instance\r
2702 )\r
2703{\r
2704 EFI_STATUS Status;\r
2705 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
2706\r
2707 InitializeListHead (&mHddPasswordConfigFormList);\r
2708\r
2709 Private = AllocateZeroPool (sizeof (HDD_PASSWORD_DXE_PRIVATE_DATA));\r
2710 if (Private == NULL) {\r
2711 return EFI_OUT_OF_RESOURCES;\r
2712 }\r
2713\r
2714 Private->Signature = HDD_PASSWORD_DXE_PRIVATE_SIGNATURE;\r
2715\r
2716 Private->ConfigAccess.ExtractConfig = HddPasswordFormExtractConfig;\r
2717 Private->ConfigAccess.RouteConfig = HddPasswordFormRouteConfig;\r
2718 Private->ConfigAccess.Callback = HddPasswordFormCallback;\r
2719\r
2720 //\r
2721 // Install Device Path Protocol and Config Access protocol to driver handle\r
2722 //\r
2723 Status = gBS->InstallMultipleProtocolInterfaces (\r
2724 &Private->DriverHandle,\r
2725 &gEfiDevicePathProtocolGuid,\r
2726 &mHddPasswordHiiVendorDevicePath,\r
2727 &gEfiHiiConfigAccessProtocolGuid,\r
2728 &Private->ConfigAccess,\r
2729 NULL\r
2730 );\r
2731 ASSERT_EFI_ERROR (Status);\r
2732 if (EFI_ERROR (Status)) {\r
2733 FreePool(Private);\r
2734 return Status;\r
2735 }\r
2736\r
2737 //\r
2738 // Publish our HII data\r
2739 //\r
2740 Private->HiiHandle = HiiAddPackages (\r
2741 &mHddPasswordVendorGuid,\r
2742 Private->DriverHandle,\r
2743 HddPasswordDxeStrings,\r
2744 HddPasswordBin,\r
2745 NULL\r
2746 );\r
2747 if (Private->HiiHandle == NULL) {\r
2748 FreePool(Private);\r
2749 return EFI_OUT_OF_RESOURCES;\r
2750 }\r
2751\r
2752 *Instance = Private;\r
2753 return Status;\r
2754}\r
2755\r
2756/**\r
2757 Main entry for this driver.\r
2758\r
2759 @param ImageHandle Image handle this driver.\r
2760 @param SystemTable Pointer to SystemTable.\r
2761\r
d6b926e7 2762 @retval EFI_SUCCESS This function always complete successfully.\r
e8959f81
HW
2763\r
2764**/\r
2765EFI_STATUS\r
2766EFIAPI\r
2767HddPasswordDxeInit (\r
2768 IN EFI_HANDLE ImageHandle,\r
2769 IN EFI_SYSTEM_TABLE *SystemTable\r
2770 )\r
2771{\r
2772 EFI_STATUS Status;\r
2773 HDD_PASSWORD_DXE_PRIVATE_DATA *Private;\r
fcf8bdcd 2774 VOID *Registration;\r
e8959f81
HW
2775 EFI_EVENT EndOfDxeEvent;\r
2776 EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
2777\r
2778 Private = NULL;\r
2779\r
2780 //\r
2781 // Initialize the configuration form of HDD Password.\r
2782 //\r
2783 Status = HddPasswordConfigFormInit (&Private);\r
2784 if (EFI_ERROR (Status)) {\r
2785 return Status;\r
2786 }\r
2787\r
2788 //\r
2789 // Register HddPasswordNotificationEvent() notify function.\r
2790 //\r
2791 EfiCreateProtocolNotifyEvent (\r
2792 &gEfiAtaPassThruProtocolGuid,\r
2793 TPL_CALLBACK,\r
2794 HddPasswordNotificationEvent,\r
2795 (VOID *)Private,\r
2796 &Registration\r
2797 );\r
2798\r
2799 Status = gBS->CreateEventEx (\r
2800 EVT_NOTIFY_SIGNAL,\r
2801 TPL_CALLBACK,\r
2802 HddPasswordEndOfDxeEventNotify,\r
2803 NULL,\r
2804 &gEfiEndOfDxeEventGroupGuid,\r
2805 &EndOfDxeEvent\r
2806 );\r
2807 ASSERT_EFI_ERROR (Status);\r
2808\r
2809 //\r
d6b926e7 2810 // Make HDD_PASSWORD_VARIABLE_NAME variable read-only.\r
e8959f81
HW
2811 //\r
2812 Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
2813 if (!EFI_ERROR (Status)) {\r
2814 Status = VariableLock->RequestToLock (\r
2815 VariableLock,\r
2816 HDD_PASSWORD_VARIABLE_NAME,\r
2817 &mHddPasswordVendorGuid\r
2818 );\r
2819 DEBUG ((DEBUG_INFO, "%a(): Lock %s variable (%r)\n", __FUNCTION__, HDD_PASSWORD_VARIABLE_NAME, Status));\r
2820 ASSERT_EFI_ERROR (Status);\r
2821 }\r
2822\r
2823 return Status;\r
2824}\r