HddPasswordDxe.c 98 KB

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