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