HddPasswordDxe.c 99 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823
  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 command, 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. // Add PcdSkipHddPasswordPrompt to determin whether to skip password prompt.
  1165. // Due to board design, device may not power off during system warm boot, which result in
  1166. // security status remain unlocked status, hence we add device security status check here.
  1167. //
  1168. // If device is in the locked status, device keeps locked and system continues booting.
  1169. // If device is in the unlocked status, system is forced shutdown for security concern.
  1170. //
  1171. if (PcdGetBool (PcdSkipHddPasswordPrompt)) {
  1172. if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
  1173. return;
  1174. } else {
  1175. gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
  1176. }
  1177. }
  1178. //
  1179. // As soon as the HDD password is in enabled state, we pop up a window to unlock hdd
  1180. // no matter it's really in locked or unlocked state.
  1181. // This way forces user to enter password every time to provide best safety.
  1182. //
  1183. while (TRUE) {
  1184. Status = PopupHddPasswordInputWindows (PopUpString, NULL, Password);
  1185. if (!EFI_ERROR (Status)) {
  1186. //
  1187. // The HDD is in locked state, unlock it by user input.
  1188. //
  1189. if (!PasswordIsFullZero (Password)) {
  1190. if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
  1191. Status = UnlockHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, Password);
  1192. } else {
  1193. //
  1194. // Use saved HDD password variable to validate HDD password
  1195. // when the device is at frozen state.
  1196. //
  1197. Status = ValidateHddPassword (ConfigFormEntry, Password);
  1198. }
  1199. } else {
  1200. Status = EFI_INVALID_PARAMETER;
  1201. }
  1202. if (!EFI_ERROR (Status)) {
  1203. CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);
  1204. if (!ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
  1205. SaveHddPasswordVariable (ConfigFormEntry, Password);
  1206. }
  1207. ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
  1208. Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);
  1209. ASSERT_EFI_ERROR (Status);
  1210. //
  1211. // Check the device security status again.
  1212. //
  1213. GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);
  1214. return;
  1215. }
  1216. ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
  1217. if (EFI_ERROR (Status)) {
  1218. RetryCount ++;
  1219. if (RetryCount < MAX_HDD_PASSWORD_RETRY_COUNT) {
  1220. do {
  1221. CreatePopUp (
  1222. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1223. &Key,
  1224. L"Invalid password.",
  1225. L"Press ENTER to retry",
  1226. NULL
  1227. );
  1228. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1229. continue;
  1230. } else {
  1231. do {
  1232. CreatePopUp (
  1233. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1234. &Key,
  1235. L"Hdd password retry count is expired. Please shutdown the machine.",
  1236. L"Press ENTER to shutdown",
  1237. NULL
  1238. );
  1239. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1240. gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
  1241. break;
  1242. }
  1243. }
  1244. } else if (Status == EFI_ABORTED) {
  1245. if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
  1246. //
  1247. // Current device in the lock status and
  1248. // User not input password and press ESC,
  1249. // keep device in lock status and continue boot.
  1250. //
  1251. do {
  1252. CreatePopUp (
  1253. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1254. &Key,
  1255. L"Press ENTER to skip the request and continue boot,",
  1256. L"Press ESC to input password again",
  1257. NULL
  1258. );
  1259. } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
  1260. if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
  1261. gST->ConOut->ClearScreen(gST->ConOut);
  1262. //
  1263. // Keep lock and continue boot.
  1264. //
  1265. return;
  1266. } else {
  1267. //
  1268. // Let user input password again.
  1269. //
  1270. continue;
  1271. }
  1272. } else {
  1273. //
  1274. // Current device in the unlock status and
  1275. // User not input password and press ESC,
  1276. // Shutdown the device.
  1277. //
  1278. do {
  1279. CreatePopUp (
  1280. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1281. &Key,
  1282. L"Press ENTER to shutdown, Press ESC to input password again",
  1283. NULL
  1284. );
  1285. } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
  1286. if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
  1287. gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
  1288. } else {
  1289. //
  1290. // Let user input password again.
  1291. //
  1292. continue;
  1293. }
  1294. }
  1295. }
  1296. }
  1297. }
  1298. }
  1299. /**
  1300. Process Set User Pwd HDD password request.
  1301. @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
  1302. @param[in] Port The port number of attached ATA device.
  1303. @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
  1304. @param[in] ConfigFormEntry The HDD Password configuration form entry.
  1305. **/
  1306. VOID
  1307. ProcessHddPasswordRequestSetUserPwd (
  1308. IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,
  1309. IN UINT16 Port,
  1310. IN UINT16 PortMultiplierPort,
  1311. IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
  1312. )
  1313. {
  1314. EFI_STATUS Status;
  1315. CHAR16 PopUpString[100];
  1316. ATA_IDENTIFY_DATA IdentifyData;
  1317. EFI_INPUT_KEY Key;
  1318. UINT16 RetryCount;
  1319. CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];
  1320. CHAR8 PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];
  1321. RetryCount = 0;
  1322. DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
  1323. if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
  1324. DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));
  1325. return;
  1326. }
  1327. if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
  1328. DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));
  1329. return;
  1330. }
  1331. UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set User Pwd: %s", ConfigFormEntry->HddString);
  1332. //
  1333. // Check the device security status.
  1334. //
  1335. if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {
  1336. while (TRUE) {
  1337. Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);
  1338. if (!EFI_ERROR (Status)) {
  1339. Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);
  1340. if (!EFI_ERROR (Status)) {
  1341. if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {
  1342. if (!PasswordIsFullZero (Password)) {
  1343. Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, 1, 0, Password);
  1344. } else {
  1345. if (ConfigFormEntry->IfrData.SecurityStatus.Enabled) {
  1346. Status = DisableHddPassword (AtaPassThru, Port, PortMultiplierPort, 0, ConfigFormEntry->Password);
  1347. } else {
  1348. Status = EFI_INVALID_PARAMETER;
  1349. }
  1350. }
  1351. if (!EFI_ERROR (Status)) {
  1352. CopyMem (ConfigFormEntry->Password, Password, HDD_PASSWORD_MAX_LENGTH);
  1353. SaveHddPasswordVariable (ConfigFormEntry, Password);
  1354. ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
  1355. ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
  1356. Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);
  1357. ASSERT_EFI_ERROR (Status);
  1358. //
  1359. // Check the device security status again.
  1360. //
  1361. GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);
  1362. return;
  1363. } else {
  1364. do {
  1365. CreatePopUp (
  1366. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1367. &Key,
  1368. L"Set/Disable User Pwd failed or invalid password.",
  1369. L"Press ENTER to retry",
  1370. NULL
  1371. );
  1372. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1373. }
  1374. } else {
  1375. do {
  1376. CreatePopUp (
  1377. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1378. &Key,
  1379. L"Passwords are not the same.",
  1380. L"Press ENTER to retry",
  1381. NULL
  1382. );
  1383. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1384. Status = EFI_INVALID_PARAMETER;
  1385. }
  1386. }
  1387. ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
  1388. ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
  1389. if (EFI_ERROR (Status)) {
  1390. RetryCount ++;
  1391. if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {
  1392. do {
  1393. CreatePopUp (
  1394. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1395. &Key,
  1396. L"Hdd password retry count is expired.",
  1397. L"Press ENTER to skip the request and continue boot",
  1398. NULL
  1399. );
  1400. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1401. gST->ConOut->ClearScreen(gST->ConOut);
  1402. return;
  1403. }
  1404. }
  1405. } else if (Status == EFI_ABORTED) {
  1406. do {
  1407. CreatePopUp (
  1408. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1409. &Key,
  1410. L"Press ENTER to skip the request and continue boot,",
  1411. L"Press ESC to input password again",
  1412. NULL
  1413. );
  1414. } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
  1415. if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
  1416. gST->ConOut->ClearScreen(gST->ConOut);
  1417. return;
  1418. } else {
  1419. //
  1420. // Let user input password again.
  1421. //
  1422. continue;
  1423. }
  1424. }
  1425. }
  1426. }
  1427. }
  1428. /**
  1429. Process Set Master Pwd HDD password request.
  1430. @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
  1431. @param[in] Port The port number of attached ATA device.
  1432. @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
  1433. @param[in] ConfigFormEntry The HDD Password configuration form entry.
  1434. **/
  1435. VOID
  1436. ProcessHddPasswordRequestSetMasterPwd (
  1437. IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,
  1438. IN UINT16 Port,
  1439. IN UINT16 PortMultiplierPort,
  1440. IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
  1441. )
  1442. {
  1443. EFI_STATUS Status;
  1444. CHAR16 PopUpString[100];
  1445. EFI_INPUT_KEY Key;
  1446. UINT16 RetryCount;
  1447. CHAR8 Password[HDD_PASSWORD_MAX_LENGTH];
  1448. CHAR8 PasswordConfirm[HDD_PASSWORD_MAX_LENGTH];
  1449. RetryCount = 0;
  1450. DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
  1451. if (ConfigFormEntry->IfrData.SecurityStatus.Frozen) {
  1452. DEBUG ((DEBUG_INFO, "%s is frozen, do nothing\n", ConfigFormEntry->HddString));
  1453. return;
  1454. }
  1455. if (ConfigFormEntry->IfrData.SecurityStatus.Locked) {
  1456. DEBUG ((DEBUG_INFO, "%s is locked, do nothing\n", ConfigFormEntry->HddString));
  1457. return;
  1458. }
  1459. UnicodeSPrint (PopUpString, sizeof (PopUpString), L"Set Master Pwd: %s", ConfigFormEntry->HddString);
  1460. //
  1461. // Check the device security status.
  1462. //
  1463. if (ConfigFormEntry->IfrData.SecurityStatus.Supported) {
  1464. while (TRUE) {
  1465. Status = PopupHddPasswordInputWindows (PopUpString, L"Please type in your new password", Password);
  1466. if (!EFI_ERROR (Status)) {
  1467. Status = PopupHddPasswordInputWindows (PopUpString, L"Please confirm your new password", PasswordConfirm);
  1468. if (!EFI_ERROR (Status)) {
  1469. if (CompareMem (Password, PasswordConfirm, HDD_PASSWORD_MAX_LENGTH) == 0) {
  1470. if (!PasswordIsFullZero (Password)) {
  1471. Status = SetHddPassword (AtaPassThru, Port, PortMultiplierPort, 1, 1, 1, Password);
  1472. } else {
  1473. Status = EFI_INVALID_PARAMETER;
  1474. }
  1475. if (!EFI_ERROR (Status)) {
  1476. ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
  1477. ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
  1478. return;
  1479. } else {
  1480. do {
  1481. CreatePopUp (
  1482. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1483. &Key,
  1484. L"Set Master Pwd failed or invalid password.",
  1485. L"Press ENTER to retry",
  1486. NULL
  1487. );
  1488. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1489. }
  1490. } else {
  1491. do {
  1492. CreatePopUp (
  1493. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1494. &Key,
  1495. L"Passwords are not the same.",
  1496. L"Press ENTER to retry",
  1497. NULL
  1498. );
  1499. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1500. Status = EFI_INVALID_PARAMETER;
  1501. }
  1502. }
  1503. ZeroMem (Password, HDD_PASSWORD_MAX_LENGTH);
  1504. ZeroMem (PasswordConfirm, HDD_PASSWORD_MAX_LENGTH);
  1505. if (EFI_ERROR (Status)) {
  1506. RetryCount ++;
  1507. if (RetryCount >= MAX_HDD_PASSWORD_RETRY_COUNT) {
  1508. do {
  1509. CreatePopUp (
  1510. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1511. &Key,
  1512. L"Hdd password retry count is expired.",
  1513. L"Press ENTER to skip the request and continue boot",
  1514. NULL
  1515. );
  1516. } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
  1517. gST->ConOut->ClearScreen(gST->ConOut);
  1518. return;
  1519. }
  1520. }
  1521. } else if (Status == EFI_ABORTED) {
  1522. do {
  1523. CreatePopUp (
  1524. EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
  1525. &Key,
  1526. L"Press ENTER to skip the request and continue boot,",
  1527. L"Press ESC to input password again",
  1528. NULL
  1529. );
  1530. } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
  1531. if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
  1532. gST->ConOut->ClearScreen(gST->ConOut);
  1533. return;
  1534. } else {
  1535. //
  1536. // Let user input password again.
  1537. //
  1538. continue;
  1539. }
  1540. }
  1541. }
  1542. }
  1543. }
  1544. /**
  1545. Process HDD password request.
  1546. @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
  1547. @param[in] Port The port number of attached ATA device.
  1548. @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
  1549. @param[in] ConfigFormEntry The HDD Password configuration form entry.
  1550. **/
  1551. VOID
  1552. ProcessHddPasswordRequest (
  1553. IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,
  1554. IN UINT16 Port,
  1555. IN UINT16 PortMultiplierPort,
  1556. IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
  1557. )
  1558. {
  1559. EFI_STATUS Status;
  1560. HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;
  1561. HDD_PASSWORD_REQUEST_VARIABLE *Variable;
  1562. UINTN VariableSize;
  1563. DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
  1564. if (mHddPasswordRequestVariable == NULL) {
  1565. Status = GetVariable2 (
  1566. HDD_PASSWORD_REQUEST_VARIABLE_NAME,
  1567. &mHddPasswordVendorGuid,
  1568. (VOID **) &Variable,
  1569. &VariableSize
  1570. );
  1571. if (EFI_ERROR (Status) || (Variable == NULL)) {
  1572. return;
  1573. }
  1574. mHddPasswordRequestVariable = Variable;
  1575. mHddPasswordRequestVariableSize = VariableSize;
  1576. //
  1577. // Delete the HDD password request variable.
  1578. //
  1579. Status = gRT->SetVariable (
  1580. HDD_PASSWORD_REQUEST_VARIABLE_NAME,
  1581. &mHddPasswordVendorGuid,
  1582. 0,
  1583. 0,
  1584. NULL
  1585. );
  1586. ASSERT_EFI_ERROR (Status);
  1587. } else {
  1588. Variable = mHddPasswordRequestVariable;
  1589. VariableSize = mHddPasswordRequestVariableSize;
  1590. }
  1591. //
  1592. // Process the HDD password requests.
  1593. //
  1594. TempVariable = Variable;
  1595. while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {
  1596. if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&
  1597. (TempVariable->Device.Device == ConfigFormEntry->Device) &&
  1598. (TempVariable->Device.Function == ConfigFormEntry->Function) &&
  1599. (TempVariable->Device.Port == ConfigFormEntry->Port) &&
  1600. (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
  1601. //
  1602. // Found the node for the HDD password device.
  1603. //
  1604. if (TempVariable->Request.UserPassword != 0) {
  1605. ProcessHddPasswordRequestSetUserPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
  1606. }
  1607. if (TempVariable->Request.MasterPassword != 0) {
  1608. ProcessHddPasswordRequestSetMasterPwd (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
  1609. }
  1610. break;
  1611. }
  1612. VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
  1613. TempVariable += 1;
  1614. }
  1615. DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
  1616. }
  1617. /**
  1618. Get saved HDD password request.
  1619. @param[in, out] ConfigFormEntry The HDD Password configuration form entry.
  1620. **/
  1621. VOID
  1622. GetSavedHddPasswordRequest (
  1623. IN OUT HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
  1624. )
  1625. {
  1626. EFI_STATUS Status;
  1627. HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;
  1628. HDD_PASSWORD_REQUEST_VARIABLE *Variable;
  1629. UINTN VariableSize;
  1630. DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
  1631. Variable = NULL;
  1632. VariableSize = 0;
  1633. Status = GetVariable2 (
  1634. HDD_PASSWORD_REQUEST_VARIABLE_NAME,
  1635. &mHddPasswordVendorGuid,
  1636. (VOID **) &Variable,
  1637. &VariableSize
  1638. );
  1639. if (EFI_ERROR (Status) || (Variable == NULL)) {
  1640. return;
  1641. }
  1642. TempVariable = Variable;
  1643. while (VariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {
  1644. if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&
  1645. (TempVariable->Device.Device == ConfigFormEntry->Device) &&
  1646. (TempVariable->Device.Function == ConfigFormEntry->Function) &&
  1647. (TempVariable->Device.Port == ConfigFormEntry->Port) &&
  1648. (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
  1649. //
  1650. // Found the node for the HDD password device.
  1651. // Get the HDD password request.
  1652. //
  1653. CopyMem (&ConfigFormEntry->IfrData.Request, &TempVariable->Request, sizeof (HDD_PASSWORD_REQUEST));
  1654. DEBUG ((
  1655. DEBUG_INFO,
  1656. "HddPasswordRequest got: 0x%x\n",
  1657. ConfigFormEntry->IfrData.Request
  1658. ));
  1659. break;
  1660. }
  1661. VariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
  1662. TempVariable += 1;
  1663. }
  1664. FreePool (Variable);
  1665. DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
  1666. }
  1667. /**
  1668. Save HDD password request.
  1669. @param[in] ConfigFormEntry The HDD Password configuration form entry.
  1670. **/
  1671. VOID
  1672. SaveHddPasswordRequest (
  1673. IN HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry
  1674. )
  1675. {
  1676. EFI_STATUS Status;
  1677. HDD_PASSWORD_REQUEST_VARIABLE *TempVariable;
  1678. UINTN TempVariableSize;
  1679. HDD_PASSWORD_REQUEST_VARIABLE *Variable;
  1680. UINTN VariableSize;
  1681. HDD_PASSWORD_REQUEST_VARIABLE *NewVariable;
  1682. UINTN NewVariableSize;
  1683. DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
  1684. DEBUG ((
  1685. DEBUG_INFO,
  1686. "HddPasswordRequest to save: 0x%x\n",
  1687. ConfigFormEntry->IfrData.Request
  1688. ));
  1689. Variable = NULL;
  1690. VariableSize = 0;
  1691. NewVariable = NULL;
  1692. NewVariableSize = 0;
  1693. Status = GetVariable2 (
  1694. HDD_PASSWORD_REQUEST_VARIABLE_NAME,
  1695. &mHddPasswordVendorGuid,
  1696. (VOID **) &Variable,
  1697. &VariableSize
  1698. );
  1699. if (!EFI_ERROR (Status) && (Variable != NULL)) {
  1700. TempVariable = Variable;
  1701. TempVariableSize = VariableSize;
  1702. while (TempVariableSize >= sizeof (HDD_PASSWORD_REQUEST_VARIABLE)) {
  1703. if ((TempVariable->Device.Bus == ConfigFormEntry->Bus) &&
  1704. (TempVariable->Device.Device == ConfigFormEntry->Device) &&
  1705. (TempVariable->Device.Function == ConfigFormEntry->Function) &&
  1706. (TempVariable->Device.Port == ConfigFormEntry->Port) &&
  1707. (TempVariable->Device.PortMultiplierPort == ConfigFormEntry->PortMultiplierPort)) {
  1708. //
  1709. // Found the node for the HDD password device.
  1710. // Update the HDD password request.
  1711. //
  1712. CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));
  1713. NewVariable = Variable;
  1714. NewVariableSize = VariableSize;
  1715. break;
  1716. }
  1717. TempVariableSize -= sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
  1718. TempVariable += 1;
  1719. }
  1720. if (NewVariable == NULL) {
  1721. //
  1722. // The node for the HDD password device is not found.
  1723. // Create node for the HDD password device.
  1724. //
  1725. NewVariableSize = VariableSize + sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
  1726. NewVariable = AllocateZeroPool (NewVariableSize);
  1727. ASSERT (NewVariable != NULL);
  1728. CopyMem (NewVariable, Variable, VariableSize);
  1729. TempVariable = (HDD_PASSWORD_REQUEST_VARIABLE *) ((UINTN) NewVariable + VariableSize);
  1730. TempVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;
  1731. TempVariable->Device.Device = (UINT8) ConfigFormEntry->Device;
  1732. TempVariable->Device.Function = (UINT8) ConfigFormEntry->Function;
  1733. TempVariable->Device.Port = ConfigFormEntry->Port;
  1734. TempVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;
  1735. CopyMem (&TempVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));
  1736. }
  1737. } else {
  1738. NewVariableSize = sizeof (HDD_PASSWORD_REQUEST_VARIABLE);
  1739. NewVariable = AllocateZeroPool (NewVariableSize);
  1740. ASSERT (NewVariable != NULL);
  1741. NewVariable->Device.Bus = (UINT8) ConfigFormEntry->Bus;
  1742. NewVariable->Device.Device = (UINT8) ConfigFormEntry->Device;
  1743. NewVariable->Device.Function = (UINT8) ConfigFormEntry->Function;
  1744. NewVariable->Device.Port = ConfigFormEntry->Port;
  1745. NewVariable->Device.PortMultiplierPort = ConfigFormEntry->PortMultiplierPort;
  1746. CopyMem (&NewVariable->Request, &ConfigFormEntry->IfrData.Request, sizeof (HDD_PASSWORD_REQUEST));
  1747. }
  1748. Status = gRT->SetVariable (
  1749. HDD_PASSWORD_REQUEST_VARIABLE_NAME,
  1750. &mHddPasswordVendorGuid,
  1751. EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
  1752. NewVariableSize,
  1753. NewVariable
  1754. );
  1755. if (EFI_ERROR (Status)) {
  1756. DEBUG ((DEBUG_INFO, "HddPasswordRequest variable set failed (%r)\n", Status));
  1757. }
  1758. if (NewVariable != Variable) {
  1759. FreePool (NewVariable);
  1760. }
  1761. if (Variable != NULL) {
  1762. FreePool (Variable);
  1763. }
  1764. DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
  1765. }
  1766. /**
  1767. Get the HDD Password configuration form entry by the index of the goto opcode activated.
  1768. @param[in] Index The 0-based index of the goto opcode activated.
  1769. @return The HDD Password configuration form entry found.
  1770. **/
  1771. HDD_PASSWORD_CONFIG_FORM_ENTRY *
  1772. HddPasswordGetConfigFormEntryByIndex (
  1773. IN UINT32 Index
  1774. )
  1775. {
  1776. LIST_ENTRY *Entry;
  1777. UINT32 CurrentIndex;
  1778. HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;
  1779. CurrentIndex = 0;
  1780. ConfigFormEntry = NULL;
  1781. EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
  1782. if (CurrentIndex == Index) {
  1783. ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
  1784. break;
  1785. }
  1786. CurrentIndex++;
  1787. }
  1788. return ConfigFormEntry;
  1789. }
  1790. /**
  1791. This function allows the caller to request the current
  1792. configuration for one or more named elements. The resulting
  1793. string is in <ConfigAltResp> format. Any and all alternative
  1794. configuration strings shall also be appended to the end of the
  1795. current configuration string. If they are, they must appear
  1796. after the current configuration. They must contain the same
  1797. routing (GUID, NAME, PATH) as the current configuration string.
  1798. They must have an additional description indicating the type of
  1799. alternative configuration the string represents,
  1800. "ALTCFG=<StringToken>". That <StringToken> (when
  1801. converted from Hex UNICODE to binary) is a reference to a
  1802. string in the associated string pack.
  1803. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  1804. @param[in] Request A null-terminated Unicode string in
  1805. <ConfigRequest> format. Note that this
  1806. includes the routing information as well as
  1807. the configurable name / value pairs. It is
  1808. invalid for this string to be in
  1809. <MultiConfigRequest> format.
  1810. @param[out] Progress On return, points to a character in the
  1811. Request string. Points to the string's null
  1812. terminator if request was successful. Points
  1813. to the most recent "&" before the first
  1814. failing name / value pair (or the beginning
  1815. of the string if the failure is in the first
  1816. name / value pair) if the request was not
  1817. successful.
  1818. @param[out] Results A null-terminated Unicode string in
  1819. <ConfigAltResp> format which has all values
  1820. filled in for the names in the Request string.
  1821. String to be allocated by the called function.
  1822. @retval EFI_SUCCESS The Results string is filled with the
  1823. values corresponding to all requested
  1824. names.
  1825. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
  1826. parts of the results that must be
  1827. stored awaiting possible future
  1828. protocols.
  1829. @retval EFI_INVALID_PARAMETER For example, passing in a NULL
  1830. for the Request parameter
  1831. would result in this type of
  1832. error. In this case, the
  1833. Progress parameter would be
  1834. set to NULL.
  1835. @retval EFI_NOT_FOUND Routing data doesn't match any
  1836. known driver. Progress set to the
  1837. first character in the routing header.
  1838. Note: There is no requirement that the
  1839. driver validate the routing data. It
  1840. must skip the <ConfigHdr> in order to
  1841. process the names.
  1842. @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
  1843. to most recent & before the
  1844. error or the beginning of the
  1845. string.
  1846. @retval EFI_INVALID_PARAMETER Unknown name. Progress points
  1847. to the & before the name in
  1848. question.Currently not implemented.
  1849. **/
  1850. EFI_STATUS
  1851. EFIAPI
  1852. HddPasswordFormExtractConfig (
  1853. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  1854. IN CONST EFI_STRING Request,
  1855. OUT EFI_STRING *Progress,
  1856. OUT EFI_STRING *Results
  1857. )
  1858. {
  1859. EFI_STATUS Status;
  1860. UINTN BufferSize;
  1861. HDD_PASSWORD_CONFIG *IfrData;
  1862. HDD_PASSWORD_DXE_PRIVATE_DATA *Private;
  1863. EFI_STRING ConfigRequestHdr;
  1864. EFI_STRING ConfigRequest;
  1865. BOOLEAN AllocatedRequest;
  1866. UINTN Size;
  1867. if (Progress == NULL || Results == NULL) {
  1868. return EFI_INVALID_PARAMETER;
  1869. }
  1870. *Progress = Request;
  1871. if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {
  1872. return EFI_NOT_FOUND;
  1873. }
  1874. ConfigRequestHdr = NULL;
  1875. ConfigRequest = NULL;
  1876. AllocatedRequest = FALSE;
  1877. Size = 0;
  1878. Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);
  1879. IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));
  1880. ASSERT (IfrData != NULL);
  1881. if (Private->Current != NULL) {
  1882. CopyMem (IfrData, &Private->Current->IfrData, sizeof (HDD_PASSWORD_CONFIG));
  1883. }
  1884. //
  1885. // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
  1886. //
  1887. BufferSize = sizeof (HDD_PASSWORD_CONFIG);
  1888. ConfigRequest = Request;
  1889. if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
  1890. //
  1891. // Request has no request element, construct full request string.
  1892. // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
  1893. // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
  1894. //
  1895. ConfigRequestHdr = HiiConstructConfigHdr (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, Private->DriverHandle);
  1896. Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
  1897. ConfigRequest = AllocateZeroPool (Size);
  1898. ASSERT (ConfigRequest != NULL);
  1899. AllocatedRequest = TRUE;
  1900. UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
  1901. FreePool (ConfigRequestHdr);
  1902. }
  1903. Status = gHiiConfigRouting->BlockToConfig (
  1904. gHiiConfigRouting,
  1905. ConfigRequest,
  1906. (UINT8 *) IfrData,
  1907. BufferSize,
  1908. Results,
  1909. Progress
  1910. );
  1911. FreePool (IfrData);
  1912. //
  1913. // Free the allocated config request string.
  1914. //
  1915. if (AllocatedRequest) {
  1916. FreePool (ConfigRequest);
  1917. ConfigRequest = NULL;
  1918. }
  1919. //
  1920. // Set Progress string to the original request string.
  1921. //
  1922. if (Request == NULL) {
  1923. *Progress = NULL;
  1924. } else if (StrStr (Request, L"OFFSET") == NULL) {
  1925. *Progress = Request + StrLen (Request);
  1926. }
  1927. return Status;
  1928. }
  1929. /**
  1930. This function applies changes in a driver's configuration.
  1931. Input is a Configuration, which has the routing data for this
  1932. driver followed by name / value configuration pairs. The driver
  1933. must apply those pairs to its configurable storage. If the
  1934. driver's configuration is stored in a linear block of data
  1935. and the driver's name / value pairs are in <BlockConfig>
  1936. format, it may use the ConfigToBlock helper function (above) to
  1937. simplify the job. Currently not implemented.
  1938. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  1939. @param[in] Configuration A null-terminated Unicode string in
  1940. <ConfigString> format.
  1941. @param[out] Progress A pointer to a string filled in with the
  1942. offset of the most recent '&' before the
  1943. first failing name / value pair (or the
  1944. beginn ing of the string if the failure
  1945. is in the first name / value pair) or
  1946. the terminating NULL if all was
  1947. successful.
  1948. @retval EFI_SUCCESS The results have been distributed or are
  1949. awaiting distribution.
  1950. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
  1951. parts of the results that must be
  1952. stored awaiting possible future
  1953. protocols.
  1954. @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
  1955. Results parameter would result
  1956. in this type of error.
  1957. @retval EFI_NOT_FOUND Target for the specified routing data
  1958. was not found.
  1959. **/
  1960. EFI_STATUS
  1961. EFIAPI
  1962. HddPasswordFormRouteConfig (
  1963. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  1964. IN CONST EFI_STRING Configuration,
  1965. OUT EFI_STRING *Progress
  1966. )
  1967. {
  1968. if (Configuration == NULL || Progress == NULL) {
  1969. return EFI_INVALID_PARAMETER;
  1970. }
  1971. //
  1972. // Check routing data in <ConfigHdr>.
  1973. // Note: if only one Storage is used, then this checking could be skipped.
  1974. //
  1975. if (!HiiIsConfigHdrMatch (Configuration, &mHddPasswordVendorGuid, mHddPasswordVendorStorageName)) {
  1976. *Progress = Configuration;
  1977. return EFI_NOT_FOUND;
  1978. }
  1979. *Progress = Configuration + StrLen (Configuration);
  1980. return EFI_SUCCESS;
  1981. }
  1982. /**
  1983. This function is called to provide results data to the driver.
  1984. This data consists of a unique key that is used to identify
  1985. which data is either being passed back or being asked for.
  1986. @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
  1987. @param[in] Action Specifies the type of action taken by the browser.
  1988. @param[in] QuestionId A unique value which is sent to the original
  1989. exporting driver so that it can identify the type
  1990. of data to expect. The format of the data tends to
  1991. vary based on the opcode that enerated the callback.
  1992. @param[in] Type The type of value for the question.
  1993. @param[in] Value A pointer to the data being sent to the original
  1994. exporting driver.
  1995. @param[out] ActionRequest On return, points to the action requested by the
  1996. callback function.
  1997. @retval EFI_SUCCESS The callback successfully handled the action.
  1998. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
  1999. variable and its data.
  2000. @retval EFI_DEVICE_ERROR The variable could not be saved.
  2001. @retval EFI_UNSUPPORTED The specified Action is not supported by the
  2002. callback.Currently not implemented.
  2003. @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
  2004. @retval Others Other errors as indicated.
  2005. **/
  2006. EFI_STATUS
  2007. EFIAPI
  2008. HddPasswordFormCallback (
  2009. IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
  2010. IN EFI_BROWSER_ACTION Action,
  2011. IN EFI_QUESTION_ID QuestionId,
  2012. IN UINT8 Type,
  2013. IN EFI_IFR_TYPE_VALUE *Value,
  2014. OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
  2015. )
  2016. {
  2017. HDD_PASSWORD_DXE_PRIVATE_DATA *Private;
  2018. EFI_STRING_ID DeviceFormTitleToken;
  2019. HDD_PASSWORD_CONFIG *IfrData;
  2020. HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;
  2021. if (ActionRequest != NULL) {
  2022. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
  2023. } else {
  2024. return EFI_INVALID_PARAMETER;
  2025. }
  2026. if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
  2027. //
  2028. // Do nothing for other UEFI Action. Only do call back when data is changing or changed.
  2029. //
  2030. return EFI_UNSUPPORTED;
  2031. }
  2032. Private = HDD_PASSWORD_DXE_PRIVATE_FROM_THIS (This);
  2033. //
  2034. // Retrive data from Browser
  2035. //
  2036. IfrData = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG));
  2037. ASSERT (IfrData != NULL);
  2038. if (!HiiGetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData)) {
  2039. FreePool (IfrData);
  2040. return EFI_NOT_FOUND;
  2041. }
  2042. switch (QuestionId) {
  2043. case KEY_HDD_USER_PASSWORD:
  2044. if (Action == EFI_BROWSER_ACTION_CHANGED) {
  2045. DEBUG ((DEBUG_INFO, "KEY_HDD_USER_PASSWORD\n"));
  2046. ConfigFormEntry = Private->Current;
  2047. ConfigFormEntry->IfrData.Request.UserPassword = Value->b;
  2048. SaveHddPasswordRequest (ConfigFormEntry);
  2049. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
  2050. }
  2051. break;
  2052. case KEY_HDD_MASTER_PASSWORD:
  2053. if (Action == EFI_BROWSER_ACTION_CHANGED) {
  2054. DEBUG ((DEBUG_INFO, "KEY_HDD_MASTER_PASSWORD\n"));
  2055. ConfigFormEntry = Private->Current;
  2056. ConfigFormEntry->IfrData.Request.MasterPassword = Value->b;
  2057. SaveHddPasswordRequest (ConfigFormEntry);
  2058. *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
  2059. }
  2060. break;
  2061. default:
  2062. if ((QuestionId >= KEY_HDD_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfHddDevices + KEY_HDD_DEVICE_ENTRY_BASE))) {
  2063. if (Action == EFI_BROWSER_ACTION_CHANGING) {
  2064. //
  2065. // In case goto the device configuration form, update the device form title.
  2066. //
  2067. ConfigFormEntry = HddPasswordGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_HDD_DEVICE_ENTRY_BASE));
  2068. ASSERT (ConfigFormEntry != NULL);
  2069. DeviceFormTitleToken = (EFI_STRING_ID) STR_HDD_SECURITY_HD;
  2070. HiiSetString (Private->HiiHandle, DeviceFormTitleToken, ConfigFormEntry->HddString, NULL);
  2071. Private->Current = ConfigFormEntry;
  2072. CopyMem (IfrData, &ConfigFormEntry->IfrData, sizeof (HDD_PASSWORD_CONFIG));
  2073. }
  2074. }
  2075. break;
  2076. }
  2077. //
  2078. // Pass changed uncommitted data back to Form Browser
  2079. //
  2080. HiiSetBrowserData (&mHddPasswordVendorGuid, mHddPasswordVendorStorageName, sizeof (HDD_PASSWORD_CONFIG), (UINT8 *) IfrData, NULL);
  2081. FreePool (IfrData);
  2082. return EFI_SUCCESS;
  2083. }
  2084. /**
  2085. Updates the HDD Password configuration form to add an entry for the attached
  2086. ata harddisk device specified by the Controller.
  2087. @param[in] HiiHandle The HII Handle associated with the registered package list.
  2088. @param[in] AtaPassThru Pointer to ATA_PASSTHRU instance.
  2089. @param[in] PciIo Pointer to PCI_IO instance.
  2090. @param[in] Controller The controller handle of the attached ata controller.
  2091. @param[in] Bus The bus number of ATA controller.
  2092. @param[in] Device The device number of ATA controller.
  2093. @param[in] Function The function number of ATA controller.
  2094. @param[in] Port The port number of attached ATA device.
  2095. @param[in] PortMultiplierPort The port number of port multiplier of attached ATA device.
  2096. @retval EFI_SUCCESS The Hdd Password configuration form is updated.
  2097. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  2098. @retval Others Other errors as indicated.
  2099. **/
  2100. EFI_STATUS
  2101. HddPasswordConfigUpdateForm (
  2102. IN EFI_HII_HANDLE HiiHandle,
  2103. IN EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru,
  2104. IN EFI_PCI_IO_PROTOCOL *PciIo,
  2105. IN EFI_HANDLE Controller,
  2106. IN UINTN Bus,
  2107. IN UINTN Device,
  2108. IN UINTN Function,
  2109. IN UINT16 Port,
  2110. IN UINT16 PortMultiplierPort
  2111. )
  2112. {
  2113. LIST_ENTRY *Entry;
  2114. HDD_PASSWORD_CONFIG_FORM_ENTRY *ConfigFormEntry;
  2115. BOOLEAN EntryExisted;
  2116. EFI_STATUS Status;
  2117. VOID *StartOpCodeHandle;
  2118. VOID *EndOpCodeHandle;
  2119. EFI_IFR_GUID_LABEL *StartLabel;
  2120. EFI_IFR_GUID_LABEL *EndLabel;
  2121. CHAR16 HddString[40];
  2122. ATA_IDENTIFY_DATA IdentifyData;
  2123. EFI_DEVICE_PATH_PROTOCOL *AtaDeviceNode;
  2124. ConfigFormEntry = NULL;
  2125. EntryExisted = FALSE;
  2126. EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
  2127. ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
  2128. if ((ConfigFormEntry->Bus == Bus) &&
  2129. (ConfigFormEntry->Device == Device) &&
  2130. (ConfigFormEntry->Function == Function) &&
  2131. (ConfigFormEntry->Port == Port) &&
  2132. (ConfigFormEntry->PortMultiplierPort == PortMultiplierPort)) {
  2133. EntryExisted = TRUE;
  2134. break;
  2135. }
  2136. }
  2137. if (!EntryExisted) {
  2138. //
  2139. // Add a new form.
  2140. //
  2141. ConfigFormEntry = AllocateZeroPool (sizeof (HDD_PASSWORD_CONFIG_FORM_ENTRY));
  2142. if (ConfigFormEntry == NULL) {
  2143. return EFI_OUT_OF_RESOURCES;
  2144. }
  2145. InitializeListHead (&ConfigFormEntry->Link);
  2146. ConfigFormEntry->Controller = Controller;
  2147. ConfigFormEntry->Bus = Bus;
  2148. ConfigFormEntry->Device = Device;
  2149. ConfigFormEntry->Function = Function;
  2150. ConfigFormEntry->Port = Port;
  2151. ConfigFormEntry->PortMultiplierPort = PortMultiplierPort;
  2152. ConfigFormEntry->AtaPassThru = AtaPassThru;
  2153. 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));
  2154. //
  2155. // Construct the device path for the HDD password device
  2156. //
  2157. Status = AtaPassThru->BuildDevicePath (
  2158. AtaPassThru,
  2159. Port,
  2160. PortMultiplierPort,
  2161. &AtaDeviceNode
  2162. );
  2163. if (EFI_ERROR (Status)) {
  2164. return Status;
  2165. }
  2166. ConfigFormEntry->DevicePath = AppendDevicePathNode (DevicePathFromHandle (Controller), AtaDeviceNode);
  2167. FreePool (AtaDeviceNode);
  2168. if (ConfigFormEntry->DevicePath == NULL) {
  2169. return EFI_OUT_OF_RESOURCES;
  2170. }
  2171. //
  2172. // Get attached harddisk model number
  2173. //
  2174. Status = GetHddDeviceIdentifyData (AtaPassThru, Port, PortMultiplierPort, &IdentifyData);
  2175. ASSERT_EFI_ERROR (Status);
  2176. if (EFI_ERROR (Status)) {
  2177. return Status;
  2178. }
  2179. GetHddDeviceModelNumber (&IdentifyData, HddString);
  2180. //
  2181. // Compose the HDD title string and help string of this port and create a new EFI_STRING_ID.
  2182. //
  2183. UnicodeSPrint (ConfigFormEntry->HddString, sizeof (ConfigFormEntry->HddString), L"HDD %d:%s", mNumberOfHddDevices, HddString);
  2184. ConfigFormEntry->TitleToken = HiiSetString (HiiHandle, 0, ConfigFormEntry->HddString, NULL);
  2185. ConfigFormEntry->TitleHelpToken = HiiSetString (HiiHandle, 0, L"Request to set HDD Password", NULL);
  2186. GetHddPasswordSecurityStatus (&IdentifyData, &ConfigFormEntry->IfrData);
  2187. InsertTailList (&mHddPasswordConfigFormList, &ConfigFormEntry->Link);
  2188. //
  2189. // Init OpCode Handle
  2190. //
  2191. StartOpCodeHandle = HiiAllocateOpCodeHandle ();
  2192. ASSERT (StartOpCodeHandle != NULL);
  2193. EndOpCodeHandle = HiiAllocateOpCodeHandle ();
  2194. ASSERT (EndOpCodeHandle != NULL);
  2195. //
  2196. // Create Hii Extend Label OpCode as the start opcode
  2197. //
  2198. StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  2199. StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  2200. StartLabel->Number = HDD_DEVICE_ENTRY_LABEL;
  2201. //
  2202. // Create Hii Extend Label OpCode as the end opcode
  2203. //
  2204. EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));
  2205. EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
  2206. EndLabel->Number = HDD_DEVICE_LABEL_END;
  2207. mNumberOfHddDevices = 0;
  2208. EFI_LIST_FOR_EACH (Entry, &mHddPasswordConfigFormList) {
  2209. ConfigFormEntry = BASE_CR (Entry, HDD_PASSWORD_CONFIG_FORM_ENTRY, Link);
  2210. HiiCreateGotoOpCode (
  2211. StartOpCodeHandle, // Container for dynamic created opcodes
  2212. FORMID_HDD_DEVICE_FORM, // Target Form ID
  2213. ConfigFormEntry->TitleToken, // Prompt text
  2214. ConfigFormEntry->TitleHelpToken, // Help text
  2215. EFI_IFR_FLAG_CALLBACK, // Question flag
  2216. (UINT16) (KEY_HDD_DEVICE_ENTRY_BASE + mNumberOfHddDevices) // Question ID
  2217. );
  2218. mNumberOfHddDevices++;
  2219. }
  2220. HiiUpdateForm (
  2221. HiiHandle,
  2222. &mHddPasswordVendorGuid,
  2223. FORMID_HDD_MAIN_FORM,
  2224. StartOpCodeHandle,
  2225. EndOpCodeHandle
  2226. );
  2227. HiiFreeOpCodeHandle (StartOpCodeHandle);
  2228. HiiFreeOpCodeHandle (EndOpCodeHandle);
  2229. //
  2230. // Check if device is locked and prompt for password.
  2231. //
  2232. HddPasswordRequestPassword (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
  2233. //
  2234. // Process HDD password request from last boot.
  2235. //
  2236. ProcessHddPasswordRequest (AtaPassThru, Port, PortMultiplierPort, ConfigFormEntry);
  2237. }
  2238. return EFI_SUCCESS;
  2239. }
  2240. /**
  2241. Ata Pass Thru Protocol notification event handler.
  2242. Check attached harddisk status to see if it's locked. If yes, then pop up a password windows to require user input.
  2243. It also registers a form for user configuration on Hdd password configuration.
  2244. @param[in] Event Event whose notification function is being invoked.
  2245. @param[in] Context Pointer to the notification function's context.
  2246. **/
  2247. VOID
  2248. EFIAPI
  2249. HddPasswordNotificationEvent (
  2250. IN EFI_EVENT Event,
  2251. IN VOID *Context
  2252. )
  2253. {
  2254. EFI_STATUS Status;
  2255. HDD_PASSWORD_DXE_PRIVATE_DATA *Private;
  2256. EFI_ATA_PASS_THRU_PROTOCOL *AtaPassThru;
  2257. UINT16 Port;
  2258. UINT16 PortMultiplierPort;
  2259. EFI_HANDLE Controller;
  2260. EFI_HANDLE *HandleBuffer;
  2261. UINTN HandleCount;
  2262. UINTN Index;
  2263. EFI_PCI_IO_PROTOCOL *PciIo;
  2264. UINTN SegNum;
  2265. UINTN BusNum;
  2266. UINTN DevNum;
  2267. UINTN FuncNum;
  2268. if (mHddPasswordEndOfDxe) {
  2269. gBS->CloseEvent (Event);
  2270. return;
  2271. }
  2272. Private = (HDD_PASSWORD_DXE_PRIVATE_DATA *)Context;
  2273. //
  2274. // Locate all handles of AtaPassThru protocol
  2275. //
  2276. Status = gBS->LocateHandleBuffer (
  2277. ByProtocol,
  2278. &gEfiAtaPassThruProtocolGuid,
  2279. NULL,
  2280. &HandleCount,
  2281. &HandleBuffer
  2282. );
  2283. if (EFI_ERROR (Status)) {
  2284. return ;
  2285. }
  2286. //
  2287. // Check attached hard disk status to see if it's locked
  2288. //
  2289. for (Index = 0; Index < HandleCount; Index += 1) {
  2290. Controller = HandleBuffer[Index];
  2291. Status = gBS->HandleProtocol (
  2292. Controller,
  2293. &gEfiAtaPassThruProtocolGuid,
  2294. (VOID **) &AtaPassThru
  2295. );
  2296. if (EFI_ERROR (Status)) {
  2297. break;
  2298. }
  2299. //
  2300. // Ignore those logical ATA_PASS_THRU instance.
  2301. //
  2302. if ((AtaPassThru->Mode->Attributes & EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL) == 0) {
  2303. continue;
  2304. }
  2305. Status = gBS->HandleProtocol (
  2306. Controller,
  2307. &gEfiPciIoProtocolGuid,
  2308. (VOID **) &PciIo
  2309. );
  2310. ASSERT_EFI_ERROR (Status);
  2311. if (EFI_ERROR (Status)) {
  2312. break;
  2313. }
  2314. Status = PciIo->GetLocation (
  2315. PciIo,
  2316. &SegNum,
  2317. &BusNum,
  2318. &DevNum,
  2319. &FuncNum
  2320. );
  2321. ASSERT_EFI_ERROR (Status);
  2322. if (EFI_ERROR (Status)) {
  2323. break;
  2324. }
  2325. //
  2326. // Assume and only support Segment == 0.
  2327. //
  2328. ASSERT (SegNum == 0);
  2329. //
  2330. // traverse all attached harddisk devices to update form and unlock it
  2331. //
  2332. Port = 0xFFFF;
  2333. while (TRUE) {
  2334. Status = AtaPassThru->GetNextPort (AtaPassThru, &Port);
  2335. if (EFI_ERROR (Status)) {
  2336. //
  2337. // We cannot find more legal port then we are done.
  2338. //
  2339. break;
  2340. }
  2341. PortMultiplierPort = 0xFFFF;
  2342. while (TRUE) {
  2343. Status = AtaPassThru->GetNextDevice (AtaPassThru, Port, &PortMultiplierPort);
  2344. if (EFI_ERROR (Status)) {
  2345. //
  2346. // We cannot find more legal port multiplier port number for ATA device
  2347. // on the port, then we are done.
  2348. //
  2349. break;
  2350. }
  2351. //
  2352. // Find out the attached harddisk devices.
  2353. // Try to add a HDD Password configuration page for the attached devices.
  2354. //
  2355. gBS->RestoreTPL (TPL_APPLICATION);
  2356. Status = HddPasswordConfigUpdateForm (Private->HiiHandle, AtaPassThru, PciIo, Controller, BusNum, DevNum, FuncNum, Port, PortMultiplierPort);
  2357. gBS->RaiseTPL (TPL_CALLBACK);
  2358. if (EFI_ERROR (Status)) {
  2359. break;
  2360. }
  2361. }
  2362. }
  2363. }
  2364. FreePool (HandleBuffer);
  2365. return ;
  2366. }
  2367. /**
  2368. Initialize the HDD Password configuration form.
  2369. @param[out] Instance Pointer to private instance.
  2370. @retval EFI_SUCCESS The HDD Password configuration form is initialized.
  2371. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
  2372. @retval Others Other errors as indicated.
  2373. **/
  2374. EFI_STATUS
  2375. HddPasswordConfigFormInit (
  2376. OUT HDD_PASSWORD_DXE_PRIVATE_DATA **Instance
  2377. )
  2378. {
  2379. EFI_STATUS Status;
  2380. HDD_PASSWORD_DXE_PRIVATE_DATA *Private;
  2381. InitializeListHead (&mHddPasswordConfigFormList);
  2382. Private = AllocateZeroPool (sizeof (HDD_PASSWORD_DXE_PRIVATE_DATA));
  2383. if (Private == NULL) {
  2384. return EFI_OUT_OF_RESOURCES;
  2385. }
  2386. Private->Signature = HDD_PASSWORD_DXE_PRIVATE_SIGNATURE;
  2387. Private->ConfigAccess.ExtractConfig = HddPasswordFormExtractConfig;
  2388. Private->ConfigAccess.RouteConfig = HddPasswordFormRouteConfig;
  2389. Private->ConfigAccess.Callback = HddPasswordFormCallback;
  2390. //
  2391. // Install Device Path Protocol and Config Access protocol to driver handle
  2392. //
  2393. Status = gBS->InstallMultipleProtocolInterfaces (
  2394. &Private->DriverHandle,
  2395. &gEfiDevicePathProtocolGuid,
  2396. &mHddPasswordHiiVendorDevicePath,
  2397. &gEfiHiiConfigAccessProtocolGuid,
  2398. &Private->ConfigAccess,
  2399. NULL
  2400. );
  2401. ASSERT_EFI_ERROR (Status);
  2402. if (EFI_ERROR (Status)) {
  2403. FreePool(Private);
  2404. return Status;
  2405. }
  2406. //
  2407. // Publish our HII data
  2408. //
  2409. Private->HiiHandle = HiiAddPackages (
  2410. &mHddPasswordVendorGuid,
  2411. Private->DriverHandle,
  2412. HddPasswordDxeStrings,
  2413. HddPasswordBin,
  2414. NULL
  2415. );
  2416. if (Private->HiiHandle == NULL) {
  2417. FreePool(Private);
  2418. return EFI_OUT_OF_RESOURCES;
  2419. }
  2420. *Instance = Private;
  2421. return Status;
  2422. }
  2423. /**
  2424. Main entry for this driver.
  2425. @param ImageHandle Image handle this driver.
  2426. @param SystemTable Pointer to SystemTable.
  2427. @retval EFI_SUCCESS This function always complete successfully.
  2428. **/
  2429. EFI_STATUS
  2430. EFIAPI
  2431. HddPasswordDxeInit (
  2432. IN EFI_HANDLE ImageHandle,
  2433. IN EFI_SYSTEM_TABLE *SystemTable
  2434. )
  2435. {
  2436. EFI_STATUS Status;
  2437. HDD_PASSWORD_DXE_PRIVATE_DATA *Private;
  2438. VOID *Registration;
  2439. EFI_EVENT EndOfDxeEvent;
  2440. EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
  2441. Private = NULL;
  2442. //
  2443. // Initialize the configuration form of HDD Password.
  2444. //
  2445. Status = HddPasswordConfigFormInit (&Private);
  2446. if (EFI_ERROR (Status)) {
  2447. return Status;
  2448. }
  2449. //
  2450. // Register HddPasswordNotificationEvent() notify function.
  2451. //
  2452. EfiCreateProtocolNotifyEvent (
  2453. &gEfiAtaPassThruProtocolGuid,
  2454. TPL_CALLBACK,
  2455. HddPasswordNotificationEvent,
  2456. (VOID *)Private,
  2457. &Registration
  2458. );
  2459. Status = gBS->CreateEventEx (
  2460. EVT_NOTIFY_SIGNAL,
  2461. TPL_CALLBACK,
  2462. HddPasswordEndOfDxeEventNotify,
  2463. NULL,
  2464. &gEfiEndOfDxeEventGroupGuid,
  2465. &EndOfDxeEvent
  2466. );
  2467. ASSERT_EFI_ERROR (Status);
  2468. //
  2469. // Make HDD_PASSWORD_VARIABLE_NAME variable read-only.
  2470. //
  2471. Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
  2472. if (!EFI_ERROR (Status)) {
  2473. Status = VariableLock->RequestToLock (
  2474. VariableLock,
  2475. HDD_PASSWORD_VARIABLE_NAME,
  2476. &mHddPasswordVendorGuid
  2477. );
  2478. DEBUG ((DEBUG_INFO, "%a(): Lock %s variable (%r)\n", __FUNCTION__, HDD_PASSWORD_VARIABLE_NAME, Status));
  2479. ASSERT_EFI_ERROR (Status);
  2480. }
  2481. return Status;
  2482. }