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