3 #include <Library/BaseCryptLib.h>
4 #include <openssl/x509.h>
7 #define PASSWORD_MAX 16
12 INTN (* callback
)(void *data
, void *data2
);
21 } __attribute__ ((packed
)) MokListNode
;
23 static EFI_INPUT_KEY
get_keystroke (void)
28 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1, &ST
->ConIn
->WaitForKey
,
30 uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
, &key
);
35 static EFI_STATUS
get_sha1sum (void *Data
, int DataSize
, UINT8
*hash
)
41 ctxsize
= Sha1GetContextSize();
42 ctx
= AllocatePool(ctxsize
);
45 Print(L
"Unable to allocate memory for hash context\n");
46 return EFI_OUT_OF_RESOURCES
;
50 Print(L
"Unable to initialise hash\n");
51 status
= EFI_OUT_OF_RESOURCES
;
55 if (!(Sha1Update(ctx
, Data
, DataSize
))) {
56 Print(L
"Unable to generate hash\n");
57 status
= EFI_OUT_OF_RESOURCES
;
61 if (!(Sha1Final(ctx
, hash
))) {
62 Print(L
"Unable to finalise hash\n");
63 status
= EFI_OUT_OF_RESOURCES
;
72 static MokListNode
*build_mok_list(UINT32 num
, void *Data
, UINTN DataSize
) {
74 INT64 remain
= DataSize
;
78 if (DataSize
< sizeof(UINT32
))
81 list
= AllocatePool(sizeof(MokListNode
) * num
);
84 Print(L
"Unable to allocate MOK list\n");
89 for (i
= 0; i
< num
; i
++) {
90 CopyMem(&list
[i
].MokSize
, ptr
, sizeof(UINT32
));
91 remain
-= sizeof(UINT32
) + list
[i
].MokSize
;
94 Print(L
"the list was corrupted\n");
99 ptr
+= sizeof(UINT32
);
101 ptr
+= list
[i
].MokSize
;
107 static void print_x509_name (X509_NAME
*X509Name
, CHAR16
*name
)
111 str
= X509_NAME_oneline(X509Name
, NULL
, 0);
113 Print(L
" %s:\n %a\n", name
, str
);
118 static const char *mon
[12]= {
119 "Jan","Feb","Mar","Apr","May","Jun",
120 "Jul","Aug","Sep","Oct","Nov","Dec"
123 static void print_x509_GENERALIZEDTIME_time (ASN1_TIME
*time
, CHAR16
*time_string
)
128 int y
= 0,M
= 0,d
= 0,h
= 0,m
= 0,s
= 0;
133 v
=(char *)time
->data
;
141 for (i
=0; i
<12; i
++) {
142 if ((v
[i
] > '9') || (v
[i
] < '0'))
146 y
= (v
[0]-'0')*1000+(v
[1]-'0')*100 + (v
[2]-'0')*10+(v
[3]-'0');
147 M
= (v
[4]-'0')*10+(v
[5]-'0');
149 if ((M
> 12) || (M
< 1))
152 d
= (v
[6]-'0')*10+(v
[7]-'0');
153 h
= (v
[8]-'0')*10+(v
[9]-'0');
154 m
= (v
[10]-'0')*10+(v
[11]-'0');
156 if (time
->length
>= 14 &&
157 (v
[12] >= '0') && (v
[12] <= '9') &&
158 (v
[13] >= '0') && (v
[13] <= '9')) {
159 s
= (v
[12]-'0')*10+(v
[13]-'0');
160 /* Check for fractions of seconds. */
161 if (time
->length
>= 15 && v
[14] == '.') {
162 int l
= time
->length
;
163 f
= &v
[14]; /* The decimal point. */
165 while (14 + f_len
< l
&& f
[f_len
] >= '0' &&
171 SPrint(time_string
, 0, L
"%a %2d %02d:%02d:%02d%.*a %d%a",
172 mon
[M
-1], d
, h
, m
, s
, f_len
, f
, y
, (gmt
)?" GMT":"");
177 static void print_x509_UTCTIME_time (ASN1_TIME
*time
, CHAR16
*time_string
)
182 int y
= 0,M
= 0,d
= 0,h
= 0,m
= 0,s
= 0;
185 v
=(char *)time
->data
;
194 if ((v
[i
] > '9') || (v
[i
] < '0'))
197 y
= (v
[0]-'0')*10+(v
[1]-'0');
202 M
= (v
[2]-'0')*10+(v
[3]-'0');
204 if ((M
> 12) || (M
< 1))
207 d
= (v
[4]-'0')*10+(v
[5]-'0');
208 h
= (v
[6]-'0')*10+(v
[7]-'0');
209 m
= (v
[8]-'0')*10+(v
[9]-'0');
211 if (time
->length
>=12 &&
212 (v
[10] >= '0') && (v
[10] <= '9') &&
213 (v
[11] >= '0') && (v
[11] <= '9'))
214 s
= (v
[10]-'0')*10+(v
[11]-'0');
216 SPrint(time_string
, 0, L
"%a %2d %02d:%02d:%02d %d%a",
217 mon
[M
-1], d
, h
, m
, s
, y
+1900, (gmt
)?" GMT":"");
222 static void print_x509_time (ASN1_TIME
*time
, CHAR16
*name
)
224 CHAR16 time_string
[30];
226 if (time
->type
== V_ASN1_UTCTIME
) {
227 print_x509_UTCTIME_time(time
, time_string
);
228 } else if (time
->type
== V_ASN1_GENERALIZEDTIME
) {
229 print_x509_GENERALIZEDTIME_time(time
, time_string
);
231 time_string
[0] = '\0';
234 Print(L
" %s:\n %s\n", name
, time_string
);
237 static void show_x509_info (X509
*X509Cert
)
239 ASN1_INTEGER
*serial
;
241 unsigned char hexbuf
[30];
245 serial
= X509_get_serialNumber(X509Cert
);
248 bnser
= ASN1_INTEGER_to_BN(serial
, NULL
);
249 n
= BN_bn2bin(bnser
, hexbuf
);
250 Print(L
" Serial Number:\n ");
251 for (i
= 0; i
< n
-1; i
++) {
252 Print(L
"%02x:", hexbuf
[i
]);
254 Print(L
"%02x\n", hexbuf
[n
-1]);
257 X509Name
= X509_get_issuer_name(X509Cert
);
259 print_x509_name(X509Name
, L
"Issuer");
262 X509Name
= X509_get_subject_name(X509Cert
);
264 print_x509_name(X509Name
, L
"Subject");
267 time
= X509_get_notBefore(X509Cert
);
269 print_x509_time(time
, L
"Validity from");
272 time
= X509_get_notAfter(X509Cert
);
274 print_x509_time(time
, L
"Validity till");
278 static void show_mok_info (void *Mok
, UINTN MokSize
)
280 EFI_STATUS efi_status
;
281 UINT8 hash
[SHA1_DIGEST_SIZE
];
285 if (!Mok
|| MokSize
== 0)
288 if (X509ConstructCertificate(Mok
, MokSize
, (UINT8
**) &X509Cert
) &&
290 show_x509_info(X509Cert
);
293 Print(L
" Not a valid X509 certificate: %x\n\n",
298 efi_status
= get_sha1sum(Mok
, MokSize
, hash
);
300 if (efi_status
!= EFI_SUCCESS
) {
301 Print(L
"Failed to compute MOK fingerprint\n");
305 Print(L
" Fingerprint (SHA1):\n ");
306 for (i
= 0; i
< SHA1_DIGEST_SIZE
; i
++) {
307 Print(L
" %02x", hash
[i
]);
314 static INTN
get_number ()
316 EFI_INPUT_KEY input_key
;
321 input_key
= get_keystroke();
323 if ((input_key
.UnicodeChar
< '0' ||
324 input_key
.UnicodeChar
> '9' ||
326 input_key
.UnicodeChar
!= CHAR_BACKSPACE
) {
330 if (count
== 0 && input_key
.UnicodeChar
== CHAR_BACKSPACE
)
333 Print(L
"%c", input_key
.UnicodeChar
);
335 if (input_key
.UnicodeChar
== CHAR_BACKSPACE
) {
336 input
[--count
] = '\0';
340 input
[count
++] = input_key
.UnicodeChar
;
341 } while (input_key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
348 return (INTN
)Atoi(input
);
351 static UINT8
list_keys (void *MokNew
, UINTN MokNewSize
)
354 MokListNode
*keys
= NULL
;
358 CopyMem(&MokNum
, MokNew
, sizeof(UINT32
));
360 Print(L
"No key exists\n");
364 keys
= build_mok_list(MokNum
,
365 (void *)MokNew
+ sizeof(UINT32
),
366 MokNewSize
- sizeof(UINT32
));
369 Print(L
"Failed to construct key list in MokNew\n");
374 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
375 Print(L
"Input the key number to show the details of the key or\n"
376 L
"type \'0\' to continue\n\n");
377 Print(L
"%d key(s) in the new key list\n\n", MokNum
);
379 if (key_num
> MokNum
) {
380 Print(L
"[Key %d]\n", key_num
);
381 Print(L
"No such key\n\n");
382 } else if (initial
!= 1 && key_num
> 0){
383 Print(L
"[Key %d]\n", key_num
);
384 show_mok_info(keys
[key_num
-1].Mok
, keys
[key_num
-1].MokSize
);
387 Print(L
"Key Number: ");
389 key_num
= get_number();
397 } while (key_num
!= 0);
404 static UINT8
get_line (UINT32
*length
, CHAR16
*line
, UINT32 line_max
, UINT8 show
)
410 key
= get_keystroke();
412 if ((count
>= line_max
&&
413 key
.UnicodeChar
!= CHAR_BACKSPACE
) ||
414 key
.UnicodeChar
== CHAR_NULL
||
415 key
.UnicodeChar
== CHAR_TAB
||
416 key
.UnicodeChar
== CHAR_LINEFEED
||
417 key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
421 if (count
== 0 && key
.UnicodeChar
== CHAR_BACKSPACE
) {
423 } else if (key
.UnicodeChar
== CHAR_BACKSPACE
) {
427 line
[--count
] = '\0';
432 Print(L
"%c", key
.UnicodeChar
);
435 line
[count
++] = key
.UnicodeChar
;
436 } while (key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
444 static EFI_STATUS
compute_pw_hash (void *MokNew
, UINTN MokNewSize
, CHAR16
*password
,
445 UINT32 pw_length
, UINT8
*hash
)
448 unsigned int ctxsize
;
451 ctxsize
= Sha256GetContextSize();
452 ctx
= AllocatePool(ctxsize
);
455 Print(L
"Unable to allocate memory for hash context\n");
456 return EFI_OUT_OF_RESOURCES
;
459 if (!Sha256Init(ctx
)) {
460 Print(L
"Unable to initialise hash\n");
461 status
= EFI_OUT_OF_RESOURCES
;
465 if (!(Sha256Update(ctx
, MokNew
, MokNewSize
))) {
466 Print(L
"Unable to generate hash\n");
467 status
= EFI_OUT_OF_RESOURCES
;
471 if (!(Sha256Update(ctx
, password
, pw_length
* sizeof(CHAR16
)))) {
472 Print(L
"Unable to generate hash\n");
473 status
= EFI_OUT_OF_RESOURCES
;
477 if (!(Sha256Final(ctx
, hash
))) {
478 Print(L
"Unable to finalise hash\n");
479 status
= EFI_OUT_OF_RESOURCES
;
483 status
= EFI_SUCCESS
;
488 static EFI_STATUS
store_keys (void *MokNew
, UINTN MokNewSize
, int authenticate
)
490 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
491 EFI_STATUS efi_status
;
492 UINT8 hash
[SHA256_DIGEST_SIZE
];
493 UINT8 auth
[SHA256_DIGEST_SIZE
];
496 CHAR16 password
[PASSWORD_MAX
];
498 UINT8 fail_count
= 0;
501 auth_size
= SHA256_DIGEST_SIZE
;
502 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokAuth",
504 &attributes
, &auth_size
, auth
);
507 if (efi_status
!= EFI_SUCCESS
|| auth_size
!= SHA256_DIGEST_SIZE
) {
508 Print(L
"Failed to get MokAuth %d\n", efi_status
);
512 while (fail_count
< 3) {
513 Print(L
"Password(%d-%d characters): ",
514 PASSWORD_MIN
, PASSWORD_MAX
);
515 get_line(&pw_length
, password
, PASSWORD_MAX
, 0);
518 Print(L
"At least %d characters for the password\n",
522 efi_status
= compute_pw_hash(MokNew
, MokNewSize
, password
,
525 if (efi_status
!= EFI_SUCCESS
) {
529 if (CompareMem(auth
, hash
, SHA256_DIGEST_SIZE
) != 0) {
530 Print(L
"Password doesn't match\n");
538 return EFI_ACCESS_DENIED
;
542 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5, L
"MokList",
544 EFI_VARIABLE_NON_VOLATILE
545 | EFI_VARIABLE_BOOTSERVICE_ACCESS
,
547 if (efi_status
!= EFI_SUCCESS
) {
548 Print(L
"Failed to set variable %d\n", efi_status
);
555 static UINTN
mok_enrollment_prompt (void *MokNew
, UINTN MokNewSize
, int auth
) {
558 EFI_STATUS efi_status
;
561 if (!list_keys(MokNew
, MokNewSize
)) {
565 Print(L
"Enroll the key(s)? (y/n): ");
567 get_line (&length
, line
, 1, 1);
569 if (line
[0] == 'Y' || line
[0] == 'y') {
570 efi_status
= store_keys(MokNew
, MokNewSize
, auth
);
572 if (efi_status
!= EFI_SUCCESS
) {
573 Print(L
"Failed to enroll keys\n");
578 } while (line
[0] != 'N' && line
[0] != 'n');
582 static INTN
mok_enrollment_prompt_callback (void *MokNew
, void *data2
) {
583 return mok_enrollment_prompt(MokNew
, (UINTN
)data2
, TRUE
);
586 static INTN
mok_deletion_prompt (void *MokNew
, void *data2
) {
589 EFI_STATUS efi_status
;
591 Print(L
"Erase all stored keys? (y/N): ");
593 get_line (&length
, line
, 1, 1);
595 if (line
[0] == 'Y' || line
[0] == 'y') {
596 efi_status
= store_keys(MokNew
, sizeof(UINT32
), TRUE
);
598 if (efi_status
!= EFI_SUCCESS
) {
599 Print(L
"Failed to erase keys\n");
607 static void draw_menu (struct menu_item
*items
, UINTN count
) {
610 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
612 for (i
= 0; i
< count
; i
++) {
613 uefi_call_wrapper(ST
->ConOut
->SetAttribute
, 2, ST
->ConOut
,
614 items
[i
].colour
| EFI_BACKGROUND_BLACK
);
615 Print(L
" %s\n", items
[i
].text
);
618 uefi_call_wrapper(ST
->ConOut
->SetCursorPosition
, 3, ST
->ConOut
, 0, 0);
619 uefi_call_wrapper(ST
->ConOut
->EnableCursor
, 2, ST
->ConOut
, TRUE
);
622 static void free_menu (struct menu_item
*items
, UINTN count
) {
626 for (i
=0; i
<count
; i
++) {
628 FreePool(items
[i
].text
);
635 static void run_menu (struct menu_item
*items
, UINTN count
, UINTN timeout
) {
636 UINTN index
, pos
= 0, wait
= 0;
644 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
646 draw_menu (items
, count
);
648 uefi_call_wrapper(ST
->ConOut
->SetAttribute
, 2,
650 EFI_WHITE
| EFI_BACKGROUND_BLACK
);
653 uefi_call_wrapper(ST
->ConOut
->SetCursorPosition
, 3,
654 ST
->ConOut
, 0, count
+ 1);
656 Print(L
"Booting in %d seconds\n", timeout
);
658 Print(L
"Booting in %d second\n", timeout
);
661 uefi_call_wrapper(ST
->ConOut
->SetCursorPosition
, 3, ST
->ConOut
,
663 status
= WaitForSingleEvent(ST
->ConIn
->WaitForKey
, wait
);
665 if (status
== EFI_TIMEOUT
) {
668 free_menu(items
, count
);
677 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1,
678 &ST
->ConIn
->WaitForKey
, &index
);
679 uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
,
682 switch(key
.ScanCode
) {
690 if (pos
== (count
- 1))
697 switch(key
.UnicodeChar
) {
699 case CHAR_CARRIAGE_RETURN
:
700 if (items
[pos
].callback
== NULL
) {
701 free_menu(items
, count
);
705 items
[pos
].callback(items
[pos
].data
, items
[pos
].data2
);
706 draw_menu (items
, count
);
713 static INTN
file_callback (void *data
, void *data2
) {
714 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
715 EFI_FILE_INFO
*buffer
= NULL
;
716 UINTN buffersize
= 0, readsize
;
719 CHAR16
*filename
= data
;
720 EFI_FILE
*parent
= data2
;
721 EFI_GUID file_info_guid
= EFI_FILE_INFO_ID
;
722 void *mokbuffer
= NULL
, *mok
;
723 UINTN MokSize
= 0, MokNewSize
;
726 mok
= LibGetVariableAndSize(L
"MokList", &shim_lock_guid
, &MokSize
);
728 status
= uefi_call_wrapper(parent
->Open
, 5, parent
, &file
, filename
,
729 EFI_FILE_MODE_READ
, 0);
731 if (status
!= EFI_SUCCESS
)
734 status
= uefi_call_wrapper(file
->GetInfo
, 4, file
, &file_info_guid
,
735 &buffersize
, buffer
);
737 if (status
== EFI_BUFFER_TOO_SMALL
) {
738 buffer
= AllocatePool(buffersize
);
739 status
= uefi_call_wrapper(file
->GetInfo
, 4, file
,
740 &file_info_guid
, &buffersize
,
747 readsize
= buffer
->FileSize
;
750 MokNewSize
= MokSize
+ readsize
+ sizeof(UINT32
);
751 mokbuffer
= AllocateZeroPool(MokNewSize
);
756 CopyMem(mokbuffer
, mok
, MokSize
);
757 ((UINT32
*)mokbuffer
)[0]++;
758 MokNew
= (MokListNode
*)(((char *)mokbuffer
) + MokSize
);
760 MokNewSize
= readsize
+ (2 * sizeof(UINT32
));
761 mokbuffer
= AllocateZeroPool(MokNewSize
);
765 ((UINT32
*)mokbuffer
)[0]=1;
766 MokNew
= (MokListNode
*)(((UINT32
*)mokbuffer
) + 1);
769 MokNew
->MokSize
= readsize
;
771 status
= uefi_call_wrapper(file
->Read
, 3, file
, &readsize
, &MokNew
->Mok
);
773 if (status
!= EFI_SUCCESS
)
776 mok_enrollment_prompt(mokbuffer
, MokNewSize
, FALSE
);
787 static INTN
directory_callback (void *data
, void *data2
) {
788 EFI_FILE_INFO
*buffer
= NULL
;
789 UINTN buffersize
= 0;
791 UINTN dircount
= 0, i
= 0;
792 struct menu_item
*dircontent
;
794 CHAR16
*filename
= data
;
795 EFI_FILE
*root
= data2
;
797 status
= uefi_call_wrapper(root
->Open
, 5, root
, &dir
, filename
,
798 EFI_FILE_MODE_READ
, 0);
800 if (status
!= EFI_SUCCESS
)
804 status
= uefi_call_wrapper(dir
->Read
, 3, dir
, &buffersize
,
807 if (status
== EFI_BUFFER_TOO_SMALL
) {
808 buffer
= AllocatePool(buffersize
);
809 status
= uefi_call_wrapper(dir
->Read
, 3, dir
,
810 &buffersize
, buffer
);
813 if (status
!= EFI_SUCCESS
)
819 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
820 (StrCmp(buffer
->FileName
, L
"..") == 0))
831 dircontent
= AllocatePool(sizeof(struct menu_item
) * dircount
);
833 dircontent
[0].text
= StrDuplicate(L
"..");
834 dircontent
[0].callback
= NULL
;
835 dircontent
[0].colour
= EFI_YELLOW
;
838 uefi_call_wrapper(dir
->SetPosition
, 2, dir
, 0);
841 status
= uefi_call_wrapper(dir
->Read
, 3, dir
, &buffersize
,
844 if (status
== EFI_BUFFER_TOO_SMALL
) {
845 buffer
= AllocatePool(buffersize
);
846 status
= uefi_call_wrapper(dir
->Read
, 3, dir
,
847 &buffersize
, buffer
);
850 if (status
!= EFI_SUCCESS
)
856 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
857 (StrCmp(buffer
->FileName
, L
"..") == 0))
860 if (buffer
->Attribute
& EFI_FILE_DIRECTORY
) {
861 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
862 dircontent
[i
].callback
= directory_callback
;
863 dircontent
[i
].data
= dircontent
[i
].text
;
864 dircontent
[i
].data2
= dir
;
865 dircontent
[i
].colour
= EFI_YELLOW
;
867 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
868 dircontent
[i
].callback
= file_callback
;
869 dircontent
[i
].data
= dircontent
[i
].text
;
870 dircontent
[i
].data2
= dir
;
871 dircontent
[i
].colour
= EFI_WHITE
;
880 run_menu(dircontent
, dircount
, 0);
885 static INTN
filesystem_callback (void *data
, void *data2
) {
886 EFI_FILE_INFO
*buffer
= NULL
;
887 UINTN buffersize
= 0;
889 UINTN dircount
= 0, i
= 0;
890 struct menu_item
*dircontent
;
891 EFI_FILE
*root
= data
;
893 uefi_call_wrapper(root
->SetPosition
, 2, root
, 0);
896 status
= uefi_call_wrapper(root
->Read
, 3, root
, &buffersize
,
899 if (status
== EFI_BUFFER_TOO_SMALL
) {
900 buffer
= AllocatePool(buffersize
);
901 status
= uefi_call_wrapper(root
->Read
, 3, root
,
902 &buffersize
, buffer
);
905 if (status
!= EFI_SUCCESS
)
911 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
912 (StrCmp(buffer
->FileName
, L
"..") == 0))
923 dircontent
= AllocatePool(sizeof(struct menu_item
) * dircount
);
925 dircontent
[0].text
= StrDuplicate(L
"Return to filesystem list");
926 dircontent
[0].callback
= NULL
;
927 dircontent
[0].colour
= EFI_YELLOW
;
930 uefi_call_wrapper(root
->SetPosition
, 2, root
, 0);
933 status
= uefi_call_wrapper(root
->Read
, 3, root
, &buffersize
,
936 if (status
== EFI_BUFFER_TOO_SMALL
) {
937 buffer
= AllocatePool(buffersize
);
938 status
= uefi_call_wrapper(root
->Read
, 3, root
,
939 &buffersize
, buffer
);
942 if (status
!= EFI_SUCCESS
)
948 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
949 (StrCmp(buffer
->FileName
, L
"..") == 0))
952 if (buffer
->Attribute
& EFI_FILE_DIRECTORY
) {
953 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
954 dircontent
[i
].callback
= directory_callback
;
955 dircontent
[i
].data
= dircontent
[i
].text
;
956 dircontent
[i
].data2
= root
;
957 dircontent
[i
].colour
= EFI_YELLOW
;
959 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
960 dircontent
[i
].callback
= file_callback
;
961 dircontent
[i
].data
= dircontent
[i
].text
;
962 dircontent
[i
].data2
= root
;
963 dircontent
[i
].colour
= EFI_WHITE
;
972 run_menu(dircontent
, dircount
, 0);
977 static INTN
find_fs (void *data
, void *data2
) {
978 EFI_GUID fs_guid
= SIMPLE_FILE_SYSTEM_PROTOCOL
;
980 EFI_HANDLE
**filesystem_handles
;
981 struct menu_item
*filesystems
;
983 uefi_call_wrapper(BS
->LocateHandleBuffer
, 5, ByProtocol
, &fs_guid
,
984 NULL
, &count
, &filesystem_handles
);
986 if (!count
|| !filesystem_handles
) {
987 Print(L
"No filesystems?\n");
993 filesystems
= AllocatePool(sizeof(struct menu_item
) * count
);
995 filesystems
[0].text
= StrDuplicate(L
"Exit");
996 filesystems
[0].callback
= NULL
;
997 filesystems
[0].colour
= EFI_YELLOW
;
999 for (i
=1; i
<count
; i
++) {
1000 EFI_HANDLE
*fs
= filesystem_handles
[i
-1];
1001 EFI_FILE_IO_INTERFACE
*fs_interface
;
1002 EFI_DEVICE_PATH
*path
;
1005 CHAR16
*VolumeLabel
= NULL
;
1006 EFI_FILE_SYSTEM_INFO
*buffer
= NULL
;
1007 UINTN buffersize
= 0;
1008 EFI_GUID file_info_guid
= EFI_FILE_INFO_ID
;
1010 status
= uefi_call_wrapper(BS
->HandleProtocol
, 3, fs
, &fs_guid
,
1013 if (status
!= EFI_SUCCESS
|| !fs_interface
)
1016 path
= DevicePathFromHandle(fs
);
1018 status
= uefi_call_wrapper(fs_interface
->OpenVolume
, 2,
1019 fs_interface
, &root
);
1021 if (status
!= EFI_SUCCESS
|| !root
)
1024 status
= uefi_call_wrapper(root
->GetInfo
, 4, root
,
1025 &file_info_guid
, &buffersize
,
1028 if (status
== EFI_BUFFER_TOO_SMALL
) {
1029 buffer
= AllocatePool(buffersize
);
1030 status
= uefi_call_wrapper(root
->GetInfo
, 4, root
,
1032 &buffersize
, buffer
);
1035 if (status
== EFI_SUCCESS
)
1036 VolumeLabel
= buffer
->VolumeLabel
;
1039 filesystems
[i
].text
= DevicePathToStr(path
);
1041 filesystems
[i
].text
= StrDuplicate(L
"Unknown device\n");
1043 StrCat(filesystems
[i
].text
, VolumeLabel
);
1048 filesystems
[i
].data
= root
;
1049 filesystems
[i
].data2
= NULL
;
1050 filesystems
[i
].callback
= filesystem_callback
;
1051 filesystems
[i
].colour
= EFI_YELLOW
;
1054 uefi_call_wrapper(BS
->FreePool
, 1, filesystem_handles
);
1056 run_menu(filesystems
, count
, 0);
1061 static EFI_STATUS
enter_mok_menu(EFI_HANDLE image_handle
, void *MokNew
,
1064 struct menu_item
*menu_item
;
1066 UINTN menucount
= 0;
1069 menu_item
= AllocateZeroPool(sizeof(struct menu_item
) * 3);
1071 menu_item
= AllocateZeroPool(sizeof(struct menu_item
) * 2);
1074 return EFI_OUT_OF_RESOURCES
;
1076 menu_item
[0].text
= StrDuplicate(L
"Continue boot");
1077 menu_item
[0].colour
= EFI_WHITE
;
1078 menu_item
[0].callback
= NULL
;
1083 CopyMem(&MokNum
, MokNew
, sizeof(UINT32
));
1085 menu_item
[1].text
= StrDuplicate(L
"Delete MOK");
1086 menu_item
[1].colour
= EFI_WHITE
;
1087 menu_item
[1].data
= MokNew
;
1088 menu_item
[1].callback
= mok_deletion_prompt
;
1090 menu_item
[1].text
= StrDuplicate(L
"Enroll MOK");
1091 menu_item
[1].colour
= EFI_WHITE
;
1092 menu_item
[1].data
= MokNew
;
1093 menu_item
[1].data2
= (void *)MokNewSize
;
1094 menu_item
[1].callback
= mok_enrollment_prompt_callback
;
1099 menu_item
[menucount
].text
= StrDuplicate(L
"Enroll key from disk");
1100 menu_item
[menucount
].colour
= EFI_WHITE
;
1101 menu_item
[menucount
].callback
= find_fs
;
1105 run_menu(menu_item
, menucount
, 10);
1110 static EFI_STATUS
check_mok_request(EFI_HANDLE image_handle
)
1112 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
1113 UINTN MokNewSize
= 0;
1114 void *MokNew
= NULL
;
1116 MokNew
= LibGetVariableAndSize(L
"MokNew", &shim_lock_guid
, &MokNewSize
);
1118 enter_mok_menu(image_handle
, MokNew
, MokNewSize
);
1121 if (LibDeleteVariable(L
"MokNew", &shim_lock_guid
) != EFI_SUCCESS
) {
1122 Print(L
"Failed to delete MokNew\n");
1126 LibDeleteVariable(L
"MokAuth", &shim_lock_guid
);
1131 EFI_STATUS
efi_main (EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
*systab
)
1133 EFI_STATUS efi_status
;
1135 InitializeLib(image_handle
, systab
);
1137 efi_status
= check_mok_request(image_handle
);