]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Library/TcgStorageOpalLib/TcgStorageOpalCore.c
b58597e61f93ebf2dbfce61362e79e7889b3a40b
[mirror_edk2.git] / SecurityPkg / Library / TcgStorageOpalLib / TcgStorageOpalCore.c
1 /** @file
2 Public API for Opal Core library.
3
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <Uefi.h>
10 #include <Library/BaseLib.h>
11 #include <Library/TimerLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/TcgStorageOpalLib.h>
15
16 #include "TcgStorageOpalLibInternal.h"
17
18 #pragma pack(1)
19 typedef struct {
20 UINT8 HardwareReset : 1;
21 UINT8 Reserved : 7;
22 } TCG_BLOCK_SID_CLEAR_EVENTS;
23 #pragma pack()
24
25 #define TRUSTED_COMMAND_TIMEOUT_NS ((UINT64) 5 * ((UINT64)(1000000)) * 1000) // 5 seconds
26 #define BUFFER_SIZE 512
27
28 /**
29 The function performs a Trusted Send of a Buffer containing a TCG_COM_PACKET.
30
31 @param[in] Sscp The input Ssc Protocol.
32 @param[in] MediaId The input Media id info used by Ssc Protocol.
33 @param[in] SecurityProtocol Security Protocol
34 @param[in] SpSpecific Security Protocol Specific
35 @param[in] TransferLength Transfer Length of Buffer (in bytes) - always a multiple of 512
36 @param[in] Buffer Address of Data to transfer
37 @param[in] BufferSize Full Size of Buffer, including space that may be used for padding.
38
39 **/
40 TCG_RESULT
41 OpalTrustedSend(
42 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp,
43 UINT32 MediaId,
44 UINT8 SecurityProtocol,
45 UINT16 SpSpecific,
46 UINTN TransferLength,
47 VOID *Buffer,
48 UINTN BufferSize
49 )
50 {
51 UINTN TransferLength512;
52 EFI_STATUS Status;
53
54 //
55 // Round transferLength up to a 512-byte multiple
56 //
57 TransferLength512 = (TransferLength + 511) & ~(UINTN)511;
58
59 if (TransferLength512 > BufferSize) {
60 return TcgResultFailureBufferTooSmall;
61 }
62
63 ZeroMem((UINT8*)Buffer + TransferLength, TransferLength512 - TransferLength);
64
65 Status = Sscp->SendData(
66 Sscp,
67 MediaId,
68 TRUSTED_COMMAND_TIMEOUT_NS,
69 SecurityProtocol,
70 SwapBytes16(SpSpecific),
71 TransferLength512,
72 Buffer
73 );
74
75 return Status == EFI_SUCCESS ? TcgResultSuccess : TcgResultFailure;
76 }
77
78 /**
79
80 The function performs a Trusted Receive of a Buffer containing a TCG_COM_PACKET.
81
82 @param[in] Sscp The input Ssc Protocol.
83 @param[in] MediaId The input Media id info used by Ssc Protocol.
84 @param[in] SecurityProtocol Security Protocol
85 @param[in] SpSpecific Security Protocol Specific
86 @param[in] Buffer Address of Data to transfer
87 @param[in] BufferSize Full Size of Buffer, including space that may be used for padding.
88 @param[in] EstimateTimeCost Estimate the time needed.
89
90 **/
91 TCG_RESULT
92 OpalTrustedRecv(
93 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *Sscp,
94 UINT32 MediaId,
95 UINT8 SecurityProtocol,
96 UINT16 SpSpecific,
97 VOID *Buffer,
98 UINTN BufferSize,
99 UINT32 EstimateTimeCost
100 )
101 {
102 UINTN TransferLength512;
103 UINT32 Tries;
104 TCG_COM_PACKET *ComPacket;
105 UINT32 Length;
106 UINT32 OutstandingData;
107 EFI_STATUS Status;
108 UINTN TransferSize;
109
110 //
111 // Round Buffer Size down to a 512-byte multiple
112 //
113 TransferLength512 = BufferSize & ~(UINTN)511;
114 Tries = 0;
115 ComPacket = NULL;
116 Length = 0;
117 OutstandingData = 0;
118
119 if (TransferLength512 < sizeof(TCG_COM_PACKET)) {
120 DEBUG ((DEBUG_INFO, "transferLength %u too small for ComPacket\n", TransferLength512));
121 return TcgResultFailureBufferTooSmall;
122 }
123
124 //
125 // Some devices respond with Length = 0 and OutstandingData = 1 to indicate that processing is not yet completed,
126 // so we need to retry the IF-RECV to get the actual Data.
127 // See TCG Core Spec v2 Table 45 IF-RECV ComPacket Field Values Summary
128 // This is an arbitrary number of retries, not from the spec.
129 //
130 // if user input estimate time cost(second level) value bigger than 10s, base on user input value to wait.
131 // Else, Use a max timeout of 10 seconds to wait, 5000 tries * 2ms = 10s
132 //
133 if (EstimateTimeCost > 10) {
134 Tries = EstimateTimeCost * 500; // 500 = 1000 * 1000 / 2000;
135 } else {
136 Tries = 5000;
137 }
138 while ((Tries--) > 0) {
139 ZeroMem( Buffer, BufferSize );
140 TransferSize = 0;
141
142 Status = Sscp->ReceiveData(
143 Sscp,
144 MediaId,
145 TRUSTED_COMMAND_TIMEOUT_NS,
146 SecurityProtocol,
147 SwapBytes16(SpSpecific),
148 TransferLength512,
149 Buffer,
150 &TransferSize
151 );
152 if (EFI_ERROR (Status)) {
153 return TcgResultFailure;
154 }
155
156 if (SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_1 && SecurityProtocol != TCG_OPAL_SECURITY_PROTOCOL_2) {
157 return TcgResultSuccess;
158 }
159
160 if (SpSpecific == TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY) {
161 return TcgResultSuccess;
162 }
163
164 ComPacket = (TCG_COM_PACKET*) Buffer;
165 Length = SwapBytes32(ComPacket->LengthBE);
166 OutstandingData = SwapBytes32( ComPacket->OutstandingDataBE );
167
168 if (Length != 0 && OutstandingData == 0) {
169 return TcgResultSuccess;
170 }
171
172 //
173 // Delay for 2 ms
174 //
175 MicroSecondDelay (2000);
176 }
177
178 return TcgResultFailure;
179 }
180
181 /**
182 The function performs send, recv, check comIDs, check method status action.
183
184 @param[in] Session OPAL_SESSION related to this method..
185 @param[in] SendSize Transfer Length of Buffer (in bytes) - always a multiple of 512
186 @param[in] Buffer Address of Data to transfer
187 @param[in] BufferSize Full Size of Buffer, including space that may be used for padding.
188 @param[in] ParseStruct Structure used to parse received TCG response.
189 @param[in] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
190 @param[in] EstimateTimeCost Estimate the time need to for the method.
191 **/
192 TCG_RESULT
193 EFIAPI
194 OpalPerformMethod (
195 OPAL_SESSION *Session,
196 UINT32 SendSize,
197 VOID *Buffer,
198 UINT32 BufferSize,
199 TCG_PARSE_STRUCT *ParseStruct,
200 UINT8 *MethodStatus,
201 UINT32 EstimateTimeCost
202 )
203 {
204 NULL_CHECK(Session);
205 NULL_CHECK(MethodStatus);
206
207 ERROR_CHECK(OpalTrustedSend(
208 Session->Sscp,
209 Session->MediaId,
210 TCG_OPAL_SECURITY_PROTOCOL_1,
211 Session->OpalBaseComId,
212 SendSize,
213 Buffer,
214 BufferSize
215 ));
216
217 ERROR_CHECK(OpalTrustedRecv(
218 Session->Sscp,
219 Session->MediaId,
220 TCG_OPAL_SECURITY_PROTOCOL_1,
221 Session->OpalBaseComId,
222 Buffer,
223 BufferSize,
224 EstimateTimeCost
225 ));
226
227 ERROR_CHECK(TcgInitTcgParseStruct(ParseStruct, Buffer, BufferSize));
228 ERROR_CHECK(TcgCheckComIds(ParseStruct, Session->OpalBaseComId, Session->ComIdExtension));
229 ERROR_CHECK(TcgGetMethodStatus(ParseStruct, MethodStatus));
230
231 return TcgResultSuccess;
232 }
233
234 /**
235 Trig the block sid action.
236
237 @param[in] Session OPAL_SESSION related to this method..
238 @param[in] HardwareReset Whether need to do hardware reset.
239
240 **/
241 TCG_RESULT
242 EFIAPI
243 OpalBlockSid(
244 OPAL_SESSION *Session,
245 BOOLEAN HardwareReset
246 )
247 {
248 UINT8 Buffer[BUFFER_SIZE];
249 TCG_BLOCK_SID_CLEAR_EVENTS *ClearEvents;
250
251 NULL_CHECK(Session);
252
253 //
254 // Set Hardware Reset bit
255 //
256 ClearEvents = (TCG_BLOCK_SID_CLEAR_EVENTS *) &Buffer[0];
257
258 ClearEvents->Reserved = 0;
259 ClearEvents->HardwareReset = HardwareReset;
260
261 return(OpalTrustedSend(
262 Session->Sscp,
263 Session->MediaId,
264 TCG_OPAL_SECURITY_PROTOCOL_2,
265 TCG_BLOCKSID_COMID, // hardcode ComID 0x0005
266 1,
267 Buffer,
268 BUFFER_SIZE
269 ));
270 }
271
272 /**
273
274 Reverts device using Admin SP Revert method.
275
276 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
277
278 **/
279 TCG_RESULT
280 EFIAPI
281 OpalPsidRevert(
282 OPAL_SESSION *AdminSpSession
283 )
284 {
285 //
286 // Now that base comid is known, start Session
287 // we'll attempt to start Session as PSID authority
288 // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
289 //
290 TCG_CREATE_STRUCT CreateStruct;
291 TCG_PARSE_STRUCT ParseStruct;
292 UINT32 Size;
293 UINT8 Buffer[BUFFER_SIZE];
294 UINT8 MethodStatus;
295
296 NULL_CHECK(AdminSpSession);
297
298 //
299 // Send Revert action on Admin SP
300 //
301 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
302 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
303 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
304 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
305 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD));
306 ERROR_CHECK(TcgStartParameters(&CreateStruct));
307 ERROR_CHECK(TcgEndParameters(&CreateStruct));
308 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
309 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
310 ERROR_CHECK(TcgEndPacket(&CreateStruct));
311 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
312
313 //
314 // Send Revert Method Call
315 //
316 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));
317 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
318
319 return TcgResultSuccess;
320 }
321
322 /**
323
324 Reverts device using Admin SP Revert method.
325
326 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
327 @param[in] EstimateTimeCost Estimate the time needed.
328
329 **/
330 TCG_RESULT
331 OpalPyrite2PsidRevert(
332 OPAL_SESSION *AdminSpSession,
333 UINT32 EstimateTimeCost
334 )
335 {
336 //
337 // Now that base comid is known, start Session
338 // we'll attempt to start Session as PSID authority
339 // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
340 //
341 TCG_CREATE_STRUCT CreateStruct;
342 TCG_PARSE_STRUCT ParseStruct;
343 UINT32 Size;
344 UINT8 Buffer[BUFFER_SIZE];
345 UINT8 MethodStatus;
346
347
348 NULL_CHECK(AdminSpSession);
349
350 //
351 // Send Revert action on Admin SP
352 //
353 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
354 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
355 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
356 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
357 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP, OPAL_ADMIN_SP_REVERT_METHOD));
358 ERROR_CHECK(TcgStartParameters(&CreateStruct));
359 ERROR_CHECK(TcgEndParameters(&CreateStruct));
360 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
361 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
362 ERROR_CHECK(TcgEndPacket(&CreateStruct));
363 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
364
365 //
366 // Send Revert Method Call
367 //
368 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, EstimateTimeCost));
369 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
370
371 return TcgResultSuccess;
372 }
373
374 /**
375
376 The function fills in the provided Buffer with the level 0 discovery Header
377 of the device specified.
378
379 @param[in] Session OPAL_SESSION data.
380 @param[in] BufferSize Size of Buffer provided (in bytes)
381 @param[in] BuffAddress Buffer address to fill with Level 0 Discovery response
382
383 **/
384 TCG_RESULT
385 EFIAPI
386 OpalRetrieveLevel0DiscoveryHeader(
387 OPAL_SESSION *Session,
388 UINTN BufferSize,
389 VOID *BuffAddress
390 )
391 {
392 return (OpalTrustedRecv(
393 Session->Sscp,
394 Session->MediaId,
395 TCG_OPAL_SECURITY_PROTOCOL_1, // SP
396 TCG_SP_SPECIFIC_PROTOCOL_LEVEL0_DISCOVERY, // SP_Specific
397 BuffAddress,
398 BufferSize,
399 0
400 ));
401 }
402
403 /**
404
405 The function fills in the provided Buffer with the supported protocol list
406 of the device specified.
407
408 @param[in] Session OPAL_SESSION data.
409 @param[in] BufferSize Size of Buffer provided (in bytes)
410 @param[in] BuffAddress Buffer address to fill with security protocol list
411
412 **/
413 TCG_RESULT
414 EFIAPI
415 OpalRetrieveSupportedProtocolList(
416 OPAL_SESSION *Session,
417 UINTN BufferSize,
418 VOID *BuffAddress
419 )
420 {
421 return (OpalTrustedRecv(
422 Session->Sscp,
423 Session->MediaId,
424 TCG_SECURITY_PROTOCOL_INFO, // SP
425 TCG_SP_SPECIFIC_PROTOCOL_LIST, // SP_Specific
426 BuffAddress,
427 BufferSize,
428 0
429 ));
430 }
431
432 /**
433 Starts a session with a security provider (SP).
434
435 If a session is started successfully, the caller must end the session with OpalEndSession when finished
436 performing Opal actions.
437
438 @param[in/out] Session OPAL_SESSION to initialize.
439 @param[in] SpId Security provider ID to start the session with.
440 @param[in] Write Whether the session should be read-only (FALSE) or read/write (TRUE).
441 @param[in] HostChallengeLength Length of the host challenge. Length should be 0 if hostChallenge is NULL
442 @param[in] HostChallenge Host challenge for Host Signing Authority. If NULL, then no Host Challenge will be sent.
443 @param[in] HostSigningAuthority Host Signing Authority used for start session. If NULL, then no Host Signing Authority will be sent.
444 @param[in/out] MethodStatus Status of the StartSession method; only valid if TcgResultSuccess is returned.
445
446 @return TcgResultSuccess indicates that the function completed without any internal errors.
447 The caller must inspect the MethodStatus field to determine whether the method completed successfully.
448
449 **/
450 TCG_RESULT
451 EFIAPI
452 OpalStartSession(
453 OPAL_SESSION *Session,
454 TCG_UID SpId,
455 BOOLEAN Write,
456 UINT32 HostChallengeLength,
457 const VOID *HostChallenge,
458 TCG_UID HostSigningAuthority,
459 UINT8 *MethodStatus
460 )
461 {
462 TCG_CREATE_STRUCT CreateStruct;
463 TCG_PARSE_STRUCT ParseStruct;
464 UINT32 Size;
465 UINT8 Buf[BUFFER_SIZE];
466 UINT16 ComIdExtension;
467 UINT32 HostSessionId;
468
469 ComIdExtension = 0;
470 HostSessionId = 1;
471
472 NULL_CHECK(Session);
473 NULL_CHECK(MethodStatus);
474
475 Session->ComIdExtension = ComIdExtension;
476 Session->HostSessionId = HostSessionId;
477
478 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
479 ERROR_CHECK(TcgCreateStartSession(
480 &CreateStruct,
481 &Size,
482 Session->OpalBaseComId,
483 ComIdExtension,
484 HostSessionId,
485 SpId,
486 Write,
487 HostChallengeLength,
488 HostChallenge,
489 HostSigningAuthority
490 ));
491 ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
492 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
493 return TcgResultSuccess; // return early if method failed - user must check MethodStatus
494 }
495
496 if (TcgParseSyncSession(&ParseStruct, Session->OpalBaseComId, ComIdExtension, HostSessionId, &Session->TperSessionId) != TcgResultSuccess) {
497 OpalEndSession(Session);
498 return TcgResultFailure;
499 }
500
501 return TcgResultSuccess;
502 }
503
504 /**
505 Close a session opened with OpalStartSession.
506
507 @param[in/out] Session OPAL_SESSION to end.
508
509 **/
510 TCG_RESULT
511 EFIAPI
512 OpalEndSession(
513 OPAL_SESSION *Session
514 )
515 {
516 UINT8 Buffer[BUFFER_SIZE];
517 TCG_CREATE_STRUCT CreateStruct;
518 UINT32 Size;
519 TCG_PARSE_STRUCT ParseStruct;
520
521 NULL_CHECK(Session);
522 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, sizeof(Buffer)));
523 ERROR_CHECK(TcgCreateEndSession(
524 &CreateStruct,
525 &Size,
526 Session->OpalBaseComId,
527 Session->ComIdExtension,
528 Session->HostSessionId,
529 Session->TperSessionId
530 ));
531
532 ERROR_CHECK(OpalTrustedSend(
533 Session->Sscp,
534 Session->MediaId,
535 TCG_OPAL_SECURITY_PROTOCOL_1,
536 Session->OpalBaseComId,
537 Size,
538 Buffer,
539 sizeof(Buffer)
540 ));
541
542 ERROR_CHECK(OpalTrustedRecv(
543 Session->Sscp,
544 Session->MediaId,
545 TCG_OPAL_SECURITY_PROTOCOL_1,
546 Session->OpalBaseComId,
547 Buffer,
548 sizeof(Buffer),
549 0
550 ));
551
552 ERROR_CHECK(TcgInitTcgParseStruct(&ParseStruct, Buffer, sizeof(Buffer)));
553 ERROR_CHECK(TcgCheckComIds(&ParseStruct, Session->OpalBaseComId, Session->ComIdExtension));
554
555 ERROR_CHECK(TcgGetNextEndOfSession(&ParseStruct));
556 return TcgResultSuccess;
557 }
558
559 /**
560
561 The function retrieves the MSID from the device specified
562
563 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY to perform PSID revert.
564 @param[in] MsidBufferSize Allocated Buffer Size (in bytes) for MSID allocated by caller
565 @param[in] Msid Variable Length byte sequence representing MSID of device
566 @param[in] MsidLength Actual Length of MSID retrieved from device
567
568 **/
569 TCG_RESULT
570 EFIAPI
571 OpalGetMsid(
572 OPAL_SESSION *AdminSpSession,
573 UINT32 MsidBufferSize,
574 UINT8 *Msid,
575 UINT32 *MsidLength
576 )
577 {
578 //
579 // now that base comid is known, start Session
580 // we'll attempt to start Session as PSID authority
581 // verify PSID Authority is defined in ADMIN SP authority table... is this possible?
582 //
583 TCG_CREATE_STRUCT CreateStruct;
584 TCG_PARSE_STRUCT ParseStruct;
585 UINT32 Size;
586 UINT8 MethodStatus;
587 UINT32 Col;
588 const VOID *RecvMsid;
589 UINT8 Buffer[BUFFER_SIZE];
590
591 NULL_CHECK(AdminSpSession);
592 NULL_CHECK(Msid);
593 NULL_CHECK(MsidLength);
594
595 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
596 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
597 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
598 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
599 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP_C_PIN_MSID, TCG_UID_METHOD_GET));
600 ERROR_CHECK(TcgStartParameters(&CreateStruct));
601 ERROR_CHECK(TcgAddStartList(&CreateStruct));
602 ERROR_CHECK(TcgAddStartName(&CreateStruct));
603 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
604 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_PIN_COL));
605 ERROR_CHECK(TcgAddEndName(&CreateStruct));
606 ERROR_CHECK(TcgAddStartName(&CreateStruct));
607 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
608 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_PIN_COL));
609 ERROR_CHECK(TcgAddEndName(&CreateStruct));
610 ERROR_CHECK(TcgAddEndList(&CreateStruct));
611 ERROR_CHECK(TcgEndParameters(&CreateStruct));
612 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
613 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
614 ERROR_CHECK(TcgEndPacket(&CreateStruct));
615 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
616
617 //
618 // Send MSID Method Call
619 //
620 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));
621 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
622
623 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
624 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
625 ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
626 ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
627 ERROR_CHECK(TcgGetNextByteSequence(&ParseStruct, &RecvMsid, MsidLength));
628 ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
629 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
630 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
631 ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
632
633 if (Col != OPAL_ADMIN_SP_PIN_COL) {
634 DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_PIN_COL));
635 return TcgResultFailure;
636 }
637
638 if (RecvMsid == NULL) {
639 return TcgResultFailure;
640 }
641
642 if (MsidBufferSize < *MsidLength) {
643 DEBUG ((DEBUG_INFO, "Buffer too small MsidBufferSize: %d MsidLength: %d\n", MsidBufferSize, *MsidLength));
644 return TcgResultFailureBufferTooSmall;
645 }
646
647 //
648 // copy msid into Buffer
649 //
650 CopyMem(Msid, RecvMsid, *MsidLength);
651 return TcgResultSuccess;
652 }
653
654 /**
655
656 The function retrieves the MSID from the device specified
657
658 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_ANYBODY_AUTHORITY
659 @param[out] ActiveDataRemovalMechanism Active Data Removal Mechanism that the device will use for Revert/RevertSP calls.
660
661 **/
662 TCG_RESULT
663 OpalPyrite2GetActiveDataRemovalMechanism (
664 IN OPAL_SESSION *AdminSpSession,
665 OUT UINT8 *ActiveDataRemovalMechanism
666 )
667 {
668 TCG_CREATE_STRUCT CreateStruct;
669 TCG_PARSE_STRUCT ParseStruct;
670 UINT32 Size;
671 UINT8 MethodStatus;
672 UINT32 Col;
673 UINT8 RecvActiveDataRemovalMechanism;
674 UINT8 Buffer[BUFFER_SIZE];
675
676 NULL_CHECK(AdminSpSession);
677 NULL_CHECK(ActiveDataRemovalMechanism);
678
679 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buffer, BUFFER_SIZE));
680 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
681 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
682 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
683 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_ADMIN_SP_DATA_REMOVAL_MECHANISM, TCG_UID_METHOD_GET));
684 ERROR_CHECK(TcgStartParameters(&CreateStruct));
685 ERROR_CHECK(TcgAddStartList(&CreateStruct));
686 ERROR_CHECK(TcgAddStartName(&CreateStruct));
687 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
688 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));
689 ERROR_CHECK(TcgAddEndName(&CreateStruct));
690 ERROR_CHECK(TcgAddStartName(&CreateStruct));
691 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
692 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));
693 ERROR_CHECK(TcgAddEndName(&CreateStruct));
694 ERROR_CHECK(TcgAddEndList(&CreateStruct));
695 ERROR_CHECK(TcgEndParameters(&CreateStruct));
696 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
697 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
698 ERROR_CHECK(TcgEndPacket(&CreateStruct));
699 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
700
701 //
702 // Send Get Active Data Removal Mechanism Method Call
703 //
704 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buffer, BUFFER_SIZE, &ParseStruct, &MethodStatus, 0));
705 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
706
707 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
708 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
709 ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
710 ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
711 ERROR_CHECK(TcgGetNextUINT8(&ParseStruct, &RecvActiveDataRemovalMechanism));
712 ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
713 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
714 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
715 ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
716
717 if (Col != OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL) {
718 DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_ADMIN_SP_ACTIVE_DATA_REMOVAL_MECHANISM_COL));
719 return TcgResultFailure;
720 }
721
722 if (RecvActiveDataRemovalMechanism >= ResearvedMechanism) {
723 return TcgResultFailure;
724 }
725
726 //
727 // Copy active data removal mechanism into Buffer
728 //
729 CopyMem(ActiveDataRemovalMechanism, &RecvActiveDataRemovalMechanism, sizeof(RecvActiveDataRemovalMechanism));
730 return TcgResultSuccess;
731 }
732
733 /**
734
735 The function calls the Admin SP RevertSP method on the Locking SP. If KeepUserData is True, then the optional parameter
736 to keep the user Data is set to True, otherwise the optional parameter is not provided.
737
738 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP
739 @param[in] KeepUserData Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data.
740 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
741
742 **/
743 TCG_RESULT
744 EFIAPI
745 OpalAdminRevert(
746 OPAL_SESSION *LockingSpSession,
747 BOOLEAN KeepUserData,
748 UINT8 *MethodStatus
749 )
750 {
751 UINT8 Buf[BUFFER_SIZE];
752 TCG_CREATE_STRUCT CreateStruct;
753 UINT32 Size;
754 TCG_PARSE_STRUCT ParseStruct;
755 TCG_RESULT Ret;
756
757 NULL_CHECK(LockingSpSession);
758 NULL_CHECK(MethodStatus);
759
760 //
761 // ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data
762 //
763 if (KeepUserData) {
764 //
765 // set readlocked and writelocked to false
766 //
767 Ret = OpalUpdateGlobalLockingRange(
768 LockingSpSession,
769 FALSE,
770 FALSE,
771 MethodStatus);
772
773 if (Ret != TcgResultSuccess || *MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
774 //
775 // bail out
776 //
777 return Ret;
778 }
779 }
780
781 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
782 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
783 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
784 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
785 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD));
786 ERROR_CHECK(TcgStartParameters(&CreateStruct));
787
788 if (KeepUserData) {
789 //
790 // optional parameter to keep Data after revert
791 //
792 ERROR_CHECK(TcgAddStartName(&CreateStruct));
793 ERROR_CHECK(TcgAddUINT32(&CreateStruct, 0x060000)); // weird Value but that's what spec says
794 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, KeepUserData));
795 ERROR_CHECK(TcgAddEndName(&CreateStruct));
796 }
797
798 ERROR_CHECK(TcgEndParameters(&CreateStruct));
799 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
800 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
801 ERROR_CHECK(TcgEndPacket(&CreateStruct));
802 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
803
804 //
805 // Send RevertSP method call
806 //
807 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
808
809 //
810 // Session is immediately ended by device after successful revertsp, so no need to end Session
811 //
812 if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
813 //
814 // Caller should take ownership again
815 //
816 return TcgResultSuccess;
817 } else {
818 //
819 // End Session
820 //
821 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus
822 }
823
824 return TcgResultSuccess;
825 }
826
827
828 /**
829
830 The function calls the Admin SP RevertSP method on the Locking SP. If KeepUserData is True, then the optional parameter
831 to keep the user Data is set to True, otherwise the optional parameter is not provided.
832
833 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to revertSP
834 @param[in] KeepUserData Specifies whether or not to keep user Data when performing RevertSP action. True = keeps user Data.
835 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
836 @param[in] EstimateTimeCost Estimate the time needed.
837
838 **/
839 TCG_RESULT
840 OpalPyrite2AdminRevert(
841 OPAL_SESSION *LockingSpSession,
842 BOOLEAN KeepUserData,
843 UINT8 *MethodStatus,
844 UINT32 EstimateTimeCost
845 )
846 {
847 UINT8 Buf[BUFFER_SIZE];
848 TCG_CREATE_STRUCT CreateStruct;
849 UINT32 Size;
850 TCG_PARSE_STRUCT ParseStruct;
851 TCG_RESULT Ret;
852
853 NULL_CHECK(LockingSpSession);
854 NULL_CHECK(MethodStatus);
855
856 //
857 // ReadLocked or WriteLocked must be False (per Opal spec) to guarantee revertSP can keep user Data
858 //
859 if (KeepUserData) {
860 //
861 // set readlocked and writelocked to false
862 //
863 Ret = OpalUpdateGlobalLockingRange(
864 LockingSpSession,
865 FALSE,
866 FALSE,
867 MethodStatus);
868
869 if (Ret != TcgResultSuccess || *MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
870 //
871 // bail out
872 //
873 return Ret;
874 }
875 }
876
877 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
878 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
879 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
880 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
881 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, TCG_UID_THIS_SP, OPAL_LOCKING_SP_REVERTSP_METHOD));
882 ERROR_CHECK(TcgStartParameters(&CreateStruct));
883
884 if (KeepUserData) {
885 //
886 // optional parameter to keep Data after revert
887 //
888 ERROR_CHECK(TcgAddStartName(&CreateStruct));
889 ERROR_CHECK(TcgAddUINT32(&CreateStruct, 0x060000)); // weird Value but that's what spec says
890 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, KeepUserData));
891 ERROR_CHECK(TcgAddEndName(&CreateStruct));
892 }
893
894 ERROR_CHECK(TcgEndParameters(&CreateStruct));
895 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
896 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
897 ERROR_CHECK(TcgEndPacket(&CreateStruct));
898 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
899
900 //
901 // Send RevertSP method call
902 //
903 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, EstimateTimeCost));
904
905 //
906 // Session is immediately ended by device after successful revertsp, so no need to end Session
907 //
908 if (*MethodStatus == TCG_METHOD_STATUS_CODE_SUCCESS) {
909 //
910 // Caller should take ownership again
911 //
912 return TcgResultSuccess;
913 } else {
914 //
915 // End Session
916 //
917 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus
918 }
919
920 return TcgResultSuccess;
921 }
922
923 /**
924
925 The function activates the Locking SP.
926 Once activated, per Opal spec, the ADMIN SP SID PIN is copied over to the ADMIN1 LOCKING SP PIN.
927 If the Locking SP is already enabled, then TcgResultSuccess is returned and no action occurs.
928
929 @param[in] AdminSpSession OPAL_SESSION with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY to activate Locking SP
930 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
931
932 **/
933 TCG_RESULT
934 EFIAPI
935 OpalActivateLockingSp(
936 OPAL_SESSION *AdminSpSession,
937 UINT8 *MethodStatus
938 )
939 {
940 UINT8 Buf[BUFFER_SIZE];
941 TCG_CREATE_STRUCT CreateStruct;
942 UINT32 Size;
943 TCG_PARSE_STRUCT ParseStruct;
944
945 NULL_CHECK(AdminSpSession);
946 NULL_CHECK(MethodStatus);
947
948 //
949 // Call Activate method on Locking SP
950 //
951 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
952 ERROR_CHECK(TcgStartComPacket(&CreateStruct, AdminSpSession->OpalBaseComId, AdminSpSession->ComIdExtension));
953 ERROR_CHECK(TcgStartPacket(&CreateStruct, AdminSpSession->TperSessionId, AdminSpSession->HostSessionId, 0x0, 0x0, 0x0));
954 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
955 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_UID_LOCKING_SP, OPAL_ADMIN_SP_ACTIVATE_METHOD));
956 ERROR_CHECK(TcgStartParameters(&CreateStruct));
957 ERROR_CHECK(TcgEndParameters(&CreateStruct));
958 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
959 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
960 ERROR_CHECK(TcgEndPacket(&CreateStruct));
961 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
962
963 //
964 // Send Activate method call
965 //
966 ERROR_CHECK(OpalPerformMethod(AdminSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
967 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess); // exit with success on method failure - user must inspect MethodStatus
968
969 return TcgResultSuccess;
970 }
971
972 /**
973
974 The function sets the PIN column of the specified cpinRowUid (authority) with the newPin Value.
975
976 @param[in/out] Session OPAL_SESSION to set password
977 @param[in] CpinRowUid UID of row (authority) to update PIN column
978 @param[in] NewPin New Pin to set for cpinRowUid specified
979 @param[in] NewPinLength Length in bytes of newPin
980 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
981
982 **/
983 TCG_RESULT
984 EFIAPI
985 OpalSetPassword(
986 OPAL_SESSION *Session,
987 TCG_UID CpinRowUid,
988 const VOID *NewPin,
989 UINT32 NewPinLength,
990 UINT8 *MethodStatus
991 )
992 {
993 UINT8 Buf[BUFFER_SIZE];
994 TCG_CREATE_STRUCT CreateStruct;
995 TCG_PARSE_STRUCT ParseStruct;
996 UINT32 Size;
997
998 NULL_CHECK(Session);
999 NULL_CHECK(NewPin);
1000 NULL_CHECK(MethodStatus);
1001
1002 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1003 ERROR_CHECK(TcgCreateSetCPin(
1004 &CreateStruct,
1005 &Size,
1006 Session->OpalBaseComId,
1007 Session->ComIdExtension,
1008 Session->TperSessionId,
1009 Session->HostSessionId,
1010 CpinRowUid,
1011 NewPin,
1012 NewPinLength
1013 ));
1014
1015 ERROR_CHECK(OpalPerformMethod(Session, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1016 // exit with success on method failure - user must inspect MethodStatus
1017 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1018
1019 return TcgResultSuccess;
1020 }
1021
1022 /**
1023
1024 The function sets the Enabled column to TRUE for the authorityUid provided and updates the PIN column for the cpinRowUid provided
1025 using the newPin provided. AuthorityUid and cpinRowUid should describe the same authority.
1026
1027 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to update
1028 @param[in] CpinRowUid Row UID of C_PIN table of Locking SP to update PIN
1029 @param[in] AuthorityUid UID of Locking SP authority to update Pin column with
1030 @param[in] NewPin New Password used to set Pin column
1031 @param[in] NewPinLength Length in bytes of new password
1032 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1033
1034 **/
1035 TCG_RESULT
1036 EFIAPI
1037 OpalSetLockingSpAuthorityEnabledAndPin(
1038 OPAL_SESSION *LockingSpSession,
1039 TCG_UID CpinRowUid,
1040 TCG_UID AuthorityUid,
1041 const VOID *NewPin,
1042 UINT32 NewPinLength,
1043 UINT8 *MethodStatus
1044 )
1045 {
1046 UINT8 Buf[BUFFER_SIZE];
1047 TCG_CREATE_STRUCT CreateStruct;
1048 TCG_PARSE_STRUCT ParseStruct;
1049 UINT32 Size;
1050 TCG_UID ActiveKey;
1051 TCG_RESULT Ret;
1052
1053 NULL_CHECK(LockingSpSession);
1054 NULL_CHECK(NewPin);
1055 NULL_CHECK(MethodStatus);
1056
1057 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1058 ERROR_CHECK(TcgSetAuthorityEnabled(
1059 &CreateStruct,
1060 &Size,
1061 LockingSpSession->OpalBaseComId,
1062 LockingSpSession->ComIdExtension,
1063 LockingSpSession->TperSessionId,
1064 LockingSpSession->HostSessionId,
1065 AuthorityUid,
1066 TRUE));
1067
1068 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1069
1070 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1071 DEBUG ((DEBUG_INFO, "Send Set Authority error\n"));
1072 return TcgResultFailure;
1073 }
1074
1075 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1076
1077 ERROR_CHECK(TcgCreateSetCPin(
1078 &CreateStruct,
1079 &Size,
1080 LockingSpSession->OpalBaseComId,
1081 LockingSpSession->ComIdExtension,
1082 LockingSpSession->TperSessionId,
1083 LockingSpSession->HostSessionId,
1084 CpinRowUid,
1085 NewPin,
1086 NewPinLength));
1087
1088 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1089
1090 //
1091 // allow user1 to set global range to unlocked/locked by modifying ACE_Locking_GlobalRange_SetRdLocked/SetWrLocked
1092 //
1093 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1094 ERROR_CHECK(TcgCreateSetAce(
1095 &CreateStruct,
1096 &Size,
1097 LockingSpSession->OpalBaseComId,
1098 LockingSpSession->ComIdExtension,
1099 LockingSpSession->TperSessionId,
1100 LockingSpSession->HostSessionId,
1101 OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_RDLOCKED,
1102 OPAL_LOCKING_SP_USER1_AUTHORITY,
1103 TCG_ACE_EXPRESSION_OR,
1104 OPAL_LOCKING_SP_ADMINS_AUTHORITY
1105 ));
1106
1107 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1108
1109 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1110 DEBUG ((DEBUG_INFO, "Update ACE for RDLOCKED failed\n"));
1111 return TcgResultFailure;
1112 }
1113
1114 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1115 ERROR_CHECK(TcgCreateSetAce(
1116 &CreateStruct,
1117 &Size,
1118 LockingSpSession->OpalBaseComId,
1119 LockingSpSession->ComIdExtension,
1120 LockingSpSession->TperSessionId,
1121 LockingSpSession->HostSessionId,
1122 OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_SET_WRLOCKED,
1123 OPAL_LOCKING_SP_USER1_AUTHORITY,
1124 TCG_ACE_EXPRESSION_OR,
1125 OPAL_LOCKING_SP_ADMINS_AUTHORITY
1126 ));
1127
1128 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1129
1130 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1131 DEBUG ((DEBUG_INFO, "Update ACE for WRLOCKED failed\n"));
1132 return TcgResultFailure;
1133 }
1134
1135 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1136 ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));
1137 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1138
1139 //
1140 // For Pyrite type SSC, it not supports Active Key.
1141 // So here add check logic before enable it.
1142 //
1143 Ret = OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey);
1144 if (Ret == TcgResultSuccess) {
1145 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1146 ERROR_CHECK(TcgCreateSetAce(
1147 &CreateStruct,
1148 &Size,
1149 LockingSpSession->OpalBaseComId,
1150 LockingSpSession->ComIdExtension,
1151 LockingSpSession->TperSessionId,
1152 LockingSpSession->HostSessionId,
1153 (ActiveKey == OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY) ? OPAL_LOCKING_SP_ACE_K_AES_256_GLOBALRANGE_GENKEY : OPAL_LOCKING_SP_ACE_K_AES_128_GLOBALRANGE_GENKEY,
1154 OPAL_LOCKING_SP_USER1_AUTHORITY,
1155 TCG_ACE_EXPRESSION_OR,
1156 OPAL_LOCKING_SP_ADMINS_AUTHORITY
1157 ));
1158
1159 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1160
1161 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1162 DEBUG ((DEBUG_INFO, "Update ACE for GLOBALRANGE_GENKEY failed\n"));
1163 //
1164 // Disable user1 if all permissions are not granted.
1165 //
1166 return TcgResultFailure;
1167 }
1168 }
1169
1170 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1171 ERROR_CHECK(TcgCreateSetAce(
1172 &CreateStruct,
1173 &Size,
1174 LockingSpSession->OpalBaseComId,
1175 LockingSpSession->ComIdExtension,
1176 LockingSpSession->TperSessionId,
1177 LockingSpSession->HostSessionId,
1178 OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL,
1179 OPAL_LOCKING_SP_USER1_AUTHORITY,
1180 TCG_ACE_EXPRESSION_OR,
1181 OPAL_LOCKING_SP_ADMINS_AUTHORITY
1182 ));
1183
1184 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1185
1186 if (*MethodStatus != TCG_METHOD_STATUS_CODE_SUCCESS) {
1187 DEBUG ((DEBUG_INFO, "Update ACE for OPAL_LOCKING_SP_ACE_LOCKING_GLOBALRANGE_GET_ALL failed\n"));
1188 return TcgResultFailure;
1189 }
1190
1191 return TcgResultSuccess;
1192 }
1193
1194 /**
1195
1196 The function sets the Enabled column to FALSE for the USER1 authority.
1197
1198 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY to disable User1
1199 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1200
1201 **/
1202 TCG_RESULT
1203 EFIAPI
1204 OpalDisableUser(
1205 OPAL_SESSION *LockingSpSession,
1206 UINT8 *MethodStatus
1207 )
1208 {
1209 UINT8 Buf[BUFFER_SIZE];
1210 TCG_CREATE_STRUCT CreateStruct;
1211 TCG_PARSE_STRUCT ParseStruct;
1212 UINT32 Size;
1213
1214 NULL_CHECK(LockingSpSession);
1215 NULL_CHECK(MethodStatus);
1216
1217 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1218 ERROR_CHECK(TcgSetAuthorityEnabled(
1219 &CreateStruct,
1220 &Size,
1221 LockingSpSession->OpalBaseComId,
1222 LockingSpSession->ComIdExtension,
1223 LockingSpSession->TperSessionId,
1224 LockingSpSession->HostSessionId,
1225 OPAL_LOCKING_SP_USER1_AUTHORITY,
1226 FALSE));
1227
1228 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1229
1230 return TcgResultSuccess;
1231 }
1232
1233 /**
1234
1235 The function retrieves the active key of the global locking range
1236 and calls the GenKey method on the active key retrieved.
1237
1238 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1239 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1240
1241 **/
1242 TCG_RESULT
1243 EFIAPI
1244 OpalGlobalLockingRangeGenKey(
1245 OPAL_SESSION *LockingSpSession,
1246 UINT8 *MethodStatus
1247 )
1248 {
1249 UINT8 Buf[BUFFER_SIZE];
1250 TCG_CREATE_STRUCT CreateStruct;
1251 TCG_PARSE_STRUCT ParseStruct;
1252 UINT32 Size;
1253 TCG_UID ActiveKey;
1254
1255 NULL_CHECK(LockingSpSession);
1256 NULL_CHECK(MethodStatus);
1257
1258 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1259 //
1260 // retrieve the activekey in order to know which globalrange key to generate
1261 //
1262 ERROR_CHECK(OpalCreateRetrieveGlobalLockingRangeActiveKey(LockingSpSession, &CreateStruct, &Size));
1263 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1264
1265 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1266
1267 ERROR_CHECK(OpalParseRetrieveGlobalLockingRangeActiveKey(&ParseStruct, &ActiveKey));
1268
1269 //
1270 // call genkey on ActiveKey UID
1271 //
1272 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1273 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1274 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1275 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1276 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, ActiveKey, TCG_UID_METHOD_GEN_KEY));
1277 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1278 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1279 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1280 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1281 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1282 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1283
1284 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1285
1286 return TcgResultSuccess;
1287 }
1288
1289 /**
1290
1291 The function updates the ReadLocked and WriteLocked columns of the Global Locking Range.
1292 This function is required for a user1 authority, since a user1 authority shall only have access to ReadLocked and WriteLocked columns
1293 (not ReadLockEnabled and WriteLockEnabled columns).
1294
1295 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1296 @param[in] ReadLocked Value to set ReadLocked column for Global Locking Range
1297 @param[in] WriteLocked Value to set WriteLocked column for Global Locking Range
1298 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1299
1300 **/
1301 TCG_RESULT
1302 EFIAPI
1303 OpalUpdateGlobalLockingRange(
1304 OPAL_SESSION *LockingSpSession,
1305 BOOLEAN ReadLocked,
1306 BOOLEAN WriteLocked,
1307 UINT8 *MethodStatus
1308 )
1309 {
1310 UINT8 Buf[BUFFER_SIZE];
1311 TCG_CREATE_STRUCT CreateStruct;
1312 TCG_PARSE_STRUCT ParseStruct;
1313 UINT32 Size;
1314
1315 NULL_CHECK(LockingSpSession);
1316 NULL_CHECK(MethodStatus);
1317
1318 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1319
1320 //
1321 // set global locking range values
1322 //
1323 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1324 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1325 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1326 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, TCG_UID_METHOD_SET));
1327 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1328 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1329 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x01)); // "Values"
1330 ERROR_CHECK(TcgAddStartList(&CreateStruct));
1331
1332 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1333 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x07)); // "ReadLocked"
1334 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLocked));
1335 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1336
1337 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1338 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x08)); // "WriteLocked"
1339 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLocked));
1340 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1341
1342 ERROR_CHECK(TcgAddEndList(&CreateStruct));
1343 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1344 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1345 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1346 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1347 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1348 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1349
1350 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1351 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1352
1353 return TcgResultSuccess;
1354 }
1355
1356 /**
1357
1358 The function updates the RangeStart, RangeLength, ReadLockedEnabled, WriteLockedEnabled, ReadLocked and WriteLocked columns
1359 of the specified Locking Range. This function requires admin authority of a locking SP session.
1360
1361 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to generate key
1362 @param[in] LockingRangeUid Locking range UID to set values
1363 @param[in] RangeStart Value to set RangeStart column for Locking Range
1364 @param[in] RangeLength Value to set RangeLength column for Locking Range
1365 @param[in] ReadLockEnabled Value to set readLockEnabled column for Locking Range
1366 @param[in] WriteLockEnabled Value to set writeLockEnabled column for Locking Range
1367 @param[in] ReadLocked Value to set ReadLocked column for Locking Range
1368 @param[in] WriteLocked Value to set WriteLocked column for Locking Range
1369 @param[in/out] MethodStatus Method status of last action performed. If action succeeded, it should be TCG_METHOD_STATUS_CODE_SUCCESS.
1370
1371 **/
1372 TCG_RESULT
1373 EFIAPI
1374 OpalSetLockingRange(
1375 OPAL_SESSION *LockingSpSession,
1376 TCG_UID LockingRangeUid,
1377 UINT64 RangeStart,
1378 UINT64 RangeLength,
1379 BOOLEAN ReadLockEnabled,
1380 BOOLEAN WriteLockEnabled,
1381 BOOLEAN ReadLocked,
1382 BOOLEAN WriteLocked,
1383 UINT8 *MethodStatus
1384 )
1385 {
1386 UINT8 Buf[BUFFER_SIZE];
1387 TCG_CREATE_STRUCT CreateStruct;
1388 TCG_PARSE_STRUCT ParseStruct;
1389 UINT32 Size;
1390
1391 NULL_CHECK(LockingSpSession);
1392 NULL_CHECK(MethodStatus);
1393
1394 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1395
1396 //
1397 // set locking range values
1398 //
1399 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1400 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1401 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1402 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, LockingRangeUid, TCG_UID_METHOD_SET));
1403 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1404 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1405 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x01)); // "Values"
1406 ERROR_CHECK(TcgAddStartList(&CreateStruct));
1407
1408 //
1409 // range start and range Length only apply to non-global locking ranges
1410 //
1411 if (LockingRangeUid != OPAL_LOCKING_SP_LOCKING_GLOBALRANGE) {
1412 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1413 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x03)); // "RangeStart"
1414 ERROR_CHECK(TcgAddUINT64(&CreateStruct, RangeStart));
1415 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1416
1417 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1418 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x04)); // "RangeLength"
1419 ERROR_CHECK(TcgAddUINT64(&CreateStruct, RangeLength));
1420 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1421 }
1422
1423 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1424 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x05)); // "ReadLockEnabled"
1425 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLockEnabled));
1426 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1427
1428 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1429 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x06)); // "WriteLockEnabled"
1430 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLockEnabled));
1431 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1432
1433 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1434 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x07)); // "ReadLocked"
1435 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, ReadLocked));
1436 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1437
1438 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1439 ERROR_CHECK(TcgAddUINT8(&CreateStruct, 0x08)); // "WriteLocked"
1440 ERROR_CHECK(TcgAddBOOLEAN(&CreateStruct, WriteLocked));
1441 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1442
1443 ERROR_CHECK(TcgAddEndList(&CreateStruct));
1444 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1445 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1446 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1447 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1448 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1449 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1450
1451 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, MethodStatus, 0));
1452 // Exit with success on method failure - user must inspect MethodStatus
1453 METHOD_STATUS_ERROR_CHECK(*MethodStatus, TcgResultSuccess);
1454
1455 return TcgResultSuccess;
1456 }
1457
1458 /**
1459
1460 The function populates the CreateStruct with a payload that will retrieve the global locking range active key.
1461 It is intended to be called with a session that is already started with a valid credential.
1462 The function does not send the payload.
1463
1464 @param[in] Session OPAL_SESSION to populate command for, needs ComId
1465 @param[in/out] CreateStruct Structure to populate with encoded TCG command
1466 @param[in/out] Size Size in bytes of the command created.
1467
1468 **/
1469 TCG_RESULT
1470 EFIAPI
1471 OpalCreateRetrieveGlobalLockingRangeActiveKey(
1472 const OPAL_SESSION *Session,
1473 TCG_CREATE_STRUCT *CreateStruct,
1474 UINT32 *Size
1475 )
1476 {
1477 NULL_CHECK(Session);
1478 NULL_CHECK(CreateStruct);
1479 NULL_CHECK(Size);
1480
1481 // Retrieve the activekey in order to know which globalrange key to generate
1482 ERROR_CHECK(TcgStartComPacket(CreateStruct, Session->OpalBaseComId, Session->ComIdExtension));
1483 ERROR_CHECK(TcgStartPacket(CreateStruct, Session->TperSessionId, Session->HostSessionId, 0x0, 0x0, 0x0));
1484 ERROR_CHECK(TcgStartSubPacket(CreateStruct, 0x0));
1485 ERROR_CHECK(TcgStartMethodCall(CreateStruct, OPAL_LOCKING_SP_LOCKING_GLOBALRANGE, TCG_UID_METHOD_GET));
1486 ERROR_CHECK(TcgStartParameters(CreateStruct));
1487 ERROR_CHECK(TcgAddStartList(CreateStruct));
1488 ERROR_CHECK(TcgAddStartName(CreateStruct));
1489 ERROR_CHECK(TcgAddUINT8(CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
1490 ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x0A)); // ActiveKey
1491 ERROR_CHECK(TcgAddEndName(CreateStruct));
1492 ERROR_CHECK(TcgAddStartName(CreateStruct));
1493 ERROR_CHECK(TcgAddUINT8(CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
1494 ERROR_CHECK(TcgAddUINT8(CreateStruct, 0x0A));
1495 ERROR_CHECK(TcgAddEndName(CreateStruct));
1496 ERROR_CHECK(TcgAddEndList(CreateStruct));
1497 ERROR_CHECK(TcgEndParameters(CreateStruct));
1498 ERROR_CHECK(TcgEndMethodCall(CreateStruct));
1499 ERROR_CHECK(TcgEndSubPacket(CreateStruct));
1500 ERROR_CHECK(TcgEndPacket(CreateStruct));
1501 ERROR_CHECK(TcgEndComPacket(CreateStruct, Size));
1502
1503 return TcgResultSuccess;
1504 }
1505
1506 /**
1507
1508 The function acquires the activeKey specified for the Global Locking Range from the ParseStruct.
1509
1510 @param[in] ParseStruct Structure that contains the device's response with the activekey
1511 @param[in/out] ActiveKey The UID of the active key retrieved
1512
1513 **/
1514 TCG_RESULT
1515 EFIAPI
1516 OpalParseRetrieveGlobalLockingRangeActiveKey(
1517 TCG_PARSE_STRUCT *ParseStruct,
1518 TCG_UID *ActiveKey
1519 )
1520 {
1521 UINT32 ColumnName;
1522
1523 NULL_CHECK(ParseStruct);
1524 NULL_CHECK(ActiveKey);
1525
1526 // parse response
1527 ERROR_CHECK(TcgGetNextStartList(ParseStruct));
1528 ERROR_CHECK(TcgGetNextStartList(ParseStruct));
1529 ERROR_CHECK(TcgGetNextStartName(ParseStruct));
1530 ERROR_CHECK(TcgGetNextUINT32(ParseStruct, &ColumnName));
1531 ERROR_CHECK(TcgGetNextTcgUid(ParseStruct, ActiveKey));
1532 ERROR_CHECK(TcgGetNextEndName(ParseStruct));
1533 ERROR_CHECK(TcgGetNextEndList(ParseStruct));
1534 ERROR_CHECK(TcgGetNextEndList(ParseStruct));
1535 ERROR_CHECK(TcgGetNextEndOfData(ParseStruct));
1536
1537 if (ColumnName != 0x0A) {
1538 DEBUG ((DEBUG_INFO, "Unexpected column name %u (exp 0x0A)\n", ColumnName));
1539 return TcgResultFailure;
1540 }
1541
1542 if (*ActiveKey != OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY && *ActiveKey != OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY) {
1543 DEBUG ((DEBUG_INFO, "Unexpected gen key %u (exp %u or %u)\n", *ActiveKey, OPAL_LOCKING_SP_K_AES_256_GLOBALRANGE_KEY, OPAL_LOCKING_SP_K_AES_128_GLOBALRANGE_KEY));
1544 return TcgResultFailure;
1545 }
1546
1547 return TcgResultSuccess;
1548 }
1549
1550 /**
1551
1552 The function retrieves the TryLimit column for the specified rowUid (authority).
1553
1554 @param[in] LockingSpSession OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve try limit
1555 @param[in] RowUid Row UID of the Locking SP C_PIN table to retrieve TryLimit column
1556 @param[in/out] TryLimit Value from TryLimit column
1557
1558 **/
1559 TCG_RESULT
1560 EFIAPI
1561 OpalGetTryLimit(
1562 OPAL_SESSION *LockingSpSession,
1563 TCG_UID RowUid,
1564 UINT32 *TryLimit
1565 )
1566 {
1567 TCG_CREATE_STRUCT CreateStruct;
1568 TCG_PARSE_STRUCT ParseStruct;
1569 UINT32 Size;
1570 UINT8 MethodStatus;
1571 UINT8 Buf[BUFFER_SIZE];
1572 UINT32 Col;
1573
1574 NULL_CHECK(LockingSpSession);
1575 NULL_CHECK(TryLimit);
1576
1577 ERROR_CHECK(TcgInitTcgCreateStruct(&CreateStruct, Buf, sizeof(Buf)));
1578 ERROR_CHECK(TcgStartComPacket(&CreateStruct, LockingSpSession->OpalBaseComId, LockingSpSession->ComIdExtension));
1579 ERROR_CHECK(TcgStartPacket(&CreateStruct, LockingSpSession->TperSessionId, LockingSpSession->HostSessionId, 0x0, 0x0, 0x0));
1580 ERROR_CHECK(TcgStartSubPacket(&CreateStruct, 0x0));
1581 ERROR_CHECK(TcgStartMethodCall(&CreateStruct, RowUid, TCG_UID_METHOD_GET));
1582 ERROR_CHECK(TcgStartParameters(&CreateStruct));
1583 ERROR_CHECK(TcgAddStartList(&CreateStruct));
1584 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1585 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_START_COLUMN_NAME));
1586 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1587 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1588 ERROR_CHECK(TcgAddStartName(&CreateStruct));
1589 ERROR_CHECK(TcgAddUINT8(&CreateStruct, TCG_CELL_BLOCK_END_COLUMN_NAME));
1590 ERROR_CHECK(TcgAddUINT8(&CreateStruct, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1591 ERROR_CHECK(TcgAddEndName(&CreateStruct));
1592 ERROR_CHECK(TcgAddEndList(&CreateStruct));
1593 ERROR_CHECK(TcgEndParameters(&CreateStruct));
1594 ERROR_CHECK(TcgEndMethodCall(&CreateStruct));
1595 ERROR_CHECK(TcgEndSubPacket(&CreateStruct));
1596 ERROR_CHECK(TcgEndPacket(&CreateStruct));
1597 ERROR_CHECK(TcgEndComPacket(&CreateStruct, &Size));
1598
1599 ERROR_CHECK(OpalPerformMethod(LockingSpSession, Size, Buf, sizeof(Buf), &ParseStruct, &MethodStatus, 0));
1600 METHOD_STATUS_ERROR_CHECK(MethodStatus, TcgResultFailure);
1601
1602 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
1603 ERROR_CHECK(TcgGetNextStartList(&ParseStruct));
1604 ERROR_CHECK(TcgGetNextStartName(&ParseStruct));
1605 ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, &Col));
1606 ERROR_CHECK(TcgGetNextUINT32(&ParseStruct, TryLimit));
1607 ERROR_CHECK(TcgGetNextEndName(&ParseStruct));
1608 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
1609 ERROR_CHECK(TcgGetNextEndList(&ParseStruct));
1610 ERROR_CHECK(TcgGetNextEndOfData(&ParseStruct));
1611
1612 if (Col != OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL) {
1613 DEBUG ((DEBUG_INFO, "ERROR: got col %u, expected %u\n", Col, OPAL_LOCKING_SP_C_PIN_TRYLIMIT_COL));
1614 return TcgResultFailure;
1615 }
1616
1617 return TcgResultSuccess;
1618 }
1619
1620 /**
1621
1622 Get the support attribute info.
1623
1624 @param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1625 @param[out] SupportedAttributes Return the support attribute info.
1626 @param[out] OpalBaseComId Return the base com id info.
1627
1628 **/
1629 TCG_RESULT
1630 EFIAPI
1631 OpalGetSupportedAttributesInfo(
1632 IN OPAL_SESSION *Session,
1633 OUT OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,
1634 OUT UINT16 *OpalBaseComId
1635 )
1636 {
1637 UINT8 Buffer[BUFFER_SIZE];
1638 TCG_SUPPORTED_SECURITY_PROTOCOLS *SupportedProtocols;
1639 TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader;
1640 OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat;
1641 OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat2;
1642 UINTN Size;
1643 UINTN Size2;
1644
1645 NULL_CHECK(Session);
1646 NULL_CHECK(SupportedAttributes);
1647 NULL_CHECK(OpalBaseComId);
1648
1649 ZeroMem(Buffer, BUFFER_SIZE);
1650 ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1651
1652 //
1653 // Retrieve supported protocols verify security protocol 1 is supported
1654 //
1655 SupportedProtocols = (TCG_SUPPORTED_SECURITY_PROTOCOLS*) Buffer;
1656
1657 //
1658 // Get list of supported protocols
1659 //
1660 if (OpalRetrieveSupportedProtocolList (Session, sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS), SupportedProtocols) == TcgResultFailure) {
1661 DEBUG ((DEBUG_INFO, "OpalRetrieveSupportedProtocolList failed\n"));
1662 return TcgResultFailure;
1663 }
1664
1665 SupportedAttributes->Sp1 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_1);
1666 SupportedAttributes->Sp2 = TcgIsProtocolSupported (SupportedProtocols, TCG_OPAL_SECURITY_PROTOCOL_2);
1667 SupportedAttributes->SpIeee1667 = TcgIsProtocolSupported (SupportedProtocols, TCG_SECURITY_PROTOCOL_IEEE_1667);
1668
1669 DEBUG ((DEBUG_INFO, "Supported Protocols: Sp1 %d Sp2: %d SpIeee1667 %d \n",
1670 SupportedAttributes->Sp1,
1671 SupportedAttributes->Sp2,
1672 SupportedAttributes->SpIeee1667
1673 ));
1674
1675 //
1676 // Perform level 0 discovery and assign desired feature info to Opal Disk structure
1677 //
1678 ZeroMem (Buffer, BUFFER_SIZE);
1679 if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1680 DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1681 return TcgResultFailure;
1682 }
1683
1684 //
1685 // Check for required feature descriptors
1686 //
1687 DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1688
1689 Size = 0;
1690 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V2_0_0, &Size);
1691 SupportedAttributes->OpalSsc2 = (Feat != NULL);
1692
1693 *OpalBaseComId = TCG_RESERVED_COMID;
1694
1695 //
1696 // Check Opal SCC V2 has valid settings for SID C_PIN on revert
1697 //
1698 if (SupportedAttributes->OpalSsc2 && Size >= sizeof (OPAL_SSCV2_FEATURE_DESCRIPTOR)) {
1699 //
1700 // Want opposite polarity b/c Value is greater than a bit, but we only care about non-zero vs zero
1701 //
1702 SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0);
1703 SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0);
1704 DEBUG ((DEBUG_INFO, "Opal SSC V2 InitCpinIndicator %d CpinUponRevert %d \n",
1705 SupportedAttributes->InitCpinIndicator,
1706 SupportedAttributes->CpinUponRevert
1707 ));
1708 *OpalBaseComId = SwapBytes16 (Feat->OpalSscV2.BaseComdIdBE);
1709 }
1710
1711 Size = 0;
1712 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_LITE, &Size);
1713 SupportedAttributes->OpalSscLite = (Feat != NULL);
1714
1715 if (Feat != NULL && Size >= sizeof (OPAL_SSCLITE_FEATURE_DESCRIPTOR)) {
1716 if (*OpalBaseComId == TCG_RESERVED_COMID) {
1717 //
1718 // Pin values used always match up with ComId used
1719 //
1720 *OpalBaseComId = SwapBytes16 (Feat->OpalSscLite.BaseComdIdBE);
1721 SupportedAttributes->InitCpinIndicator = (Feat->OpalSscV2.InitialCPINSIDPIN == 0);
1722 SupportedAttributes->CpinUponRevert = (Feat->OpalSscV2.CPINSIDPINRevertBehavior == 0);
1723 DEBUG ((DEBUG_INFO, "Opal SSC Lite InitCpinIndicator %d CpinUponRevert %d \n",
1724 SupportedAttributes->InitCpinIndicator,
1725 SupportedAttributes->CpinUponRevert
1726 ));
1727 }
1728 }
1729
1730 //
1731 // For some pyrite 2.0 device, it contains both pyrite 1.0 and 2.0 feature data.
1732 // so here try to get data from pyrite 2.0 feature data first.
1733 //
1734 Size = 0;
1735 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC, &Size);
1736 Size2 = 0;
1737 Feat2 = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_PYRITE_SSC_V2_0_0, &Size2);
1738 if (Feat2 != NULL && Size2 >= sizeof (PYRITE_SSCV2_FEATURE_DESCRIPTOR)) {
1739 SupportedAttributes->PyriteSscV2 = TRUE;
1740 if (*OpalBaseComId == TCG_RESERVED_COMID) {
1741 *OpalBaseComId = SwapBytes16 (Feat2->PyriteSscV2.BaseComdIdBE);
1742 SupportedAttributes->InitCpinIndicator = (Feat2->PyriteSscV2.InitialCPINSIDPIN == 0);
1743 SupportedAttributes->CpinUponRevert = (Feat2->PyriteSscV2.CPINSIDPINRevertBehavior == 0);
1744 DEBUG ((DEBUG_INFO, "Pyrite SSC V2 InitCpinIndicator %d CpinUponRevert %d \n",
1745 SupportedAttributes->InitCpinIndicator,
1746 SupportedAttributes->CpinUponRevert
1747 ));
1748 }
1749 } else {
1750 SupportedAttributes->PyriteSsc = (Feat != NULL);
1751 if (Feat != NULL && Size >= sizeof (PYRITE_SSC_FEATURE_DESCRIPTOR)) {
1752 if (*OpalBaseComId == TCG_RESERVED_COMID) {
1753 *OpalBaseComId = SwapBytes16 (Feat->PyriteSsc.BaseComdIdBE);
1754 SupportedAttributes->InitCpinIndicator = (Feat->PyriteSsc.InitialCPINSIDPIN == 0);
1755 SupportedAttributes->CpinUponRevert = (Feat->PyriteSsc.CPINSIDPINRevertBehavior == 0);
1756 DEBUG ((DEBUG_INFO, "Pyrite SSC InitCpinIndicator %d CpinUponRevert %d \n",
1757 SupportedAttributes->InitCpinIndicator,
1758 SupportedAttributes->CpinUponRevert
1759 ));
1760 }
1761 }
1762 }
1763
1764 Size = 0;
1765 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_OPAL_SSC_V1_0_0, &Size);
1766 SupportedAttributes->OpalSsc1 = (Feat != NULL);
1767 if (Feat != NULL && Size >= sizeof (OPAL_SSCV1_FEATURE_DESCRIPTOR)) {
1768 if (*OpalBaseComId == TCG_RESERVED_COMID) {
1769 *OpalBaseComId = SwapBytes16 (Feat->OpalSscV1.BaseComdIdBE);
1770 }
1771 }
1772
1773 Size = 0;
1774 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size);
1775 if (Feat != NULL && Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)) {
1776 SupportedAttributes->MediaEncryption = Feat->Locking.MediaEncryption;
1777 DEBUG ((DEBUG_INFO, "SupportedAttributes->MediaEncryption 0x%X \n", SupportedAttributes->MediaEncryption));
1778 }
1779
1780 Size = 0;
1781 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_BLOCK_SID, &Size);
1782 if (Feat != NULL && Size >= sizeof (TCG_BLOCK_SID_FEATURE_DESCRIPTOR)) {
1783 SupportedAttributes->BlockSid = TRUE;
1784 DEBUG ((DEBUG_INFO, "BlockSid Supported!!! Current Status is 0x%X \n", Feat->BlockSid.SIDBlockedState));
1785 } else {
1786 DEBUG ((DEBUG_INFO, "BlockSid Unsupported!!!"));
1787 }
1788
1789 Size = 0;
1790 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_DATA_REMOVAL, &Size);
1791 if (Feat != NULL && Size >= sizeof (DATA_REMOVAL_FEATURE_DESCRIPTOR)) {
1792 SupportedAttributes->DataRemoval = TRUE;
1793 DEBUG ((DEBUG_INFO, "DataRemoval Feature Supported!\n"));
1794 DEBUG ((DEBUG_INFO, "Operation Processing = 0x%x\n", Feat->DataRemoval.OperationProcessing));
1795 DEBUG ((DEBUG_INFO, "RemovalMechanism = 0x%x\n", Feat->DataRemoval.RemovalMechanism));
1796 DEBUG ((DEBUG_INFO, "BIT0 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit0, SwapBytes16 (Feat->DataRemoval.TimeBit0)));
1797 DEBUG ((DEBUG_INFO, "BIT1 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit1, SwapBytes16 (Feat->DataRemoval.TimeBit1)));
1798 DEBUG ((DEBUG_INFO, "BIT2 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit2, SwapBytes16 (Feat->DataRemoval.TimeBit2)));
1799 DEBUG ((DEBUG_INFO, "BIT3 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit3, SwapBytes16 (Feat->DataRemoval.TimeBit3)));
1800 DEBUG ((DEBUG_INFO, "BIT4 :: Format = 0x%x, Time = 0x%x\n", Feat->DataRemoval.FormatBit4, SwapBytes16 (Feat->DataRemoval.TimeBit4)));
1801 }
1802
1803 DEBUG ((DEBUG_INFO, "Base COMID 0x%04X \n", *OpalBaseComId));
1804
1805 return TcgResultSuccess;
1806 }
1807
1808 /**
1809
1810 Get the support attribute info.
1811
1812 @param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1813 @param[in/out] LockingFeature Return the Locking info.
1814
1815 **/
1816 TCG_RESULT
1817 EFIAPI
1818 OpalGetLockingInfo(
1819 OPAL_SESSION *Session,
1820 TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature
1821 )
1822 {
1823 UINT8 Buffer[BUFFER_SIZE];
1824 TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader;
1825 OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat;
1826 UINTN Size;
1827
1828 NULL_CHECK(Session);
1829 NULL_CHECK(LockingFeature);
1830
1831 ZeroMem(Buffer, BUFFER_SIZE);
1832 ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1833
1834 if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1835 DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1836 return TcgResultFailure;
1837 }
1838 DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1839
1840 Size = 0;
1841 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, TCG_FEATURE_LOCKING, &Size);
1842 if (Feat != NULL && Size >= sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR)) {
1843 CopyMem (LockingFeature, &Feat->Locking, sizeof (TCG_LOCKING_FEATURE_DESCRIPTOR));
1844 }
1845
1846 return TcgResultSuccess;
1847 }
1848
1849 /**
1850
1851 Get the descriptor for the specific feature code.
1852
1853 @param[in] Session OPAL_SESSION with OPAL_UID_LOCKING_SP to retrieve info.
1854 @param[in] FeatureCode The feature code user request.
1855 @param[in, out] DataSize The data size.
1856 @param[out] Data The data buffer used to save the feature descriptor.
1857
1858 **/
1859 TCG_RESULT
1860 OpalGetFeatureDescriptor (
1861 IN OPAL_SESSION *Session,
1862 IN UINT16 FeatureCode,
1863 IN OUT UINTN *DataSize,
1864 OUT VOID *Data
1865 )
1866 {
1867 UINT8 Buffer[BUFFER_SIZE];
1868 TCG_LEVEL0_DISCOVERY_HEADER *DiscoveryHeader;
1869 OPAL_LEVEL0_FEATURE_DESCRIPTOR *Feat;
1870 UINTN Size;
1871
1872 NULL_CHECK(Session);
1873 NULL_CHECK(DataSize);
1874 NULL_CHECK(Data);
1875
1876 ZeroMem(Buffer, BUFFER_SIZE);
1877 ASSERT(sizeof(Buffer) >= sizeof(TCG_SUPPORTED_SECURITY_PROTOCOLS));
1878
1879 if (OpalRetrieveLevel0DiscoveryHeader (Session, BUFFER_SIZE, Buffer) == TcgResultFailure) {
1880 DEBUG ((DEBUG_INFO, "OpalRetrieveLevel0DiscoveryHeader failed\n"));
1881 return TcgResultFailure;
1882 }
1883 DiscoveryHeader = (TCG_LEVEL0_DISCOVERY_HEADER*) Buffer;
1884
1885 Size = 0;
1886 Feat = (OPAL_LEVEL0_FEATURE_DESCRIPTOR*) TcgGetFeature (DiscoveryHeader, FeatureCode, &Size);
1887 if (Feat != NULL) {
1888 if (Size > *DataSize) {
1889 *DataSize = Size;
1890 return TcgResultFailureBufferTooSmall;
1891 }
1892
1893 *DataSize = Size;
1894 CopyMem (Data, Feat, Size);
1895 }
1896
1897 return TcgResultSuccess;
1898 }
1899
1900 /**
1901
1902 The function determines whether or not all of the requirements for the Opal Feature (not full specification)
1903 are met by the specified device.
1904
1905 @param[in] SupportedAttributes Opal device attribute.
1906
1907 **/
1908 BOOLEAN
1909 EFIAPI
1910 OpalFeatureSupported(
1911 OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes
1912 )
1913 {
1914 NULL_CHECK(SupportedAttributes);
1915
1916 if (SupportedAttributes->Sp1 == 0) {
1917 return FALSE;
1918 }
1919
1920 if (SupportedAttributes->OpalSscLite == 0 &&
1921 SupportedAttributes->OpalSsc1 == 0 &&
1922 SupportedAttributes->OpalSsc2 == 0 &&
1923 SupportedAttributes->PyriteSsc == 0 &&
1924 SupportedAttributes->PyriteSscV2 == 0
1925 ) {
1926 return FALSE;
1927 }
1928
1929 return TRUE;
1930 }
1931
1932 /**
1933
1934 The function returns whether or not the device is Opal Enabled.
1935 TRUE means that the device is partially or fully locked.
1936 This will perform a Level 0 Discovery and parse the locking feature descriptor
1937
1938 @param[in] SupportedAttributes Opal device attribute.
1939 @param[in] LockingFeature Opal device locking status.
1940
1941
1942 **/
1943 BOOLEAN
1944 EFIAPI
1945 OpalFeatureEnabled(
1946 OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,
1947 TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature
1948 )
1949 {
1950 NULL_CHECK(SupportedAttributes);
1951 NULL_CHECK(LockingFeature);
1952
1953 if (!OpalFeatureSupported (SupportedAttributes)) {
1954 return FALSE;
1955 }
1956
1957 if (LockingFeature->LockingSupported && LockingFeature->LockingEnabled) {
1958 return TRUE;
1959 }
1960
1961 return FALSE;
1962 }
1963
1964 /**
1965
1966 The function returns whether or not the device is Opal Locked.
1967 TRUE means that the device is partially or fully locked.
1968 This will perform a Level 0 Discovery and parse the locking feature descriptor
1969
1970 @param[in] SupportedAttributes Opal device attribute.
1971 @param[in] LockingFeature Opal device locking status.
1972
1973 **/
1974 BOOLEAN
1975 OpalDeviceLocked(
1976 OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,
1977 TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature
1978 )
1979 {
1980 NULL_CHECK(SupportedAttributes);
1981 NULL_CHECK(LockingFeature);
1982
1983 if (!OpalFeatureEnabled (SupportedAttributes, LockingFeature)) {
1984 return FALSE;
1985 }
1986
1987 return LockingFeature->Locked;
1988 }
1989