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