blob: bb988dfb6da3139960e5ec0a8448f5b768fdb9a6 [file] [log] [blame]
lijuang7d235f42015-07-16 20:19:45 +08001/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2*
3* Redistribution and use in source and binary forms, with or without
4* modification, are permitted provided that the following conditions are
5* met:
6* * Redistributions of source code must retain the above copyright
7* notice, this list of conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above
9* copyright notice, this list of conditions and the following
10* disclaimer in the documentation and/or other materials provided
11* with the distribution.
12* * Neither the name of The Linux Foundation nor the names of its
13* contributors may be used to endorse or promote products derived
14* from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#include <debug.h>
30#include <reg.h>
31#include <stdlib.h>
32#include <openssl/evp.h>
33#include <dev/fbcon.h>
34#include <kernel/thread.h>
35#include <display_menu.h>
36#include <menu_keys_detect.h>
37#include <boot_verifier.h>
38#include <string.h>
39#include <platform.h>
lijuang4ece1e72015-08-14 21:02:36 +080040#include <smem.h>
41#include <target.h>
42#include <sys/types.h>
43#include <../../../app/aboot/devinfo.h>
lijuang7d235f42015-07-16 20:19:45 +080044
lijuang4ece1e72015-08-14 21:02:36 +080045static const char *unlock_menu_common_msg = "If you unlock the bootloader, "\
lijuang7d235f42015-07-16 20:19:45 +080046 "you will be able to install "\
47 "custom operating system on this phone.\n\n"\
48 "A custom OS is not subject to the same testing "\
49 "as the original OS, "\
50 "and can cause your phone and installed "\
51 "applications to stop working properly.\n\n"\
52 "To prevent unauthorized access to your personal data, "\
53 "unlocking the bootloader will also delete all personal "\
54 "data from your phone(a \"fatory data reset\").\n\n"\
55 "Press the Volume Up/Down buttons to select Yes "\
56 "or No. Then press the Power button to continue.\n";
57
lijuang4ece1e72015-08-14 21:02:36 +080058#define YELLOW_WARNING_MSG "Your device has loaded a diffrent operating "\
59 "system\n\nTo learn more, visit:\n"
lijuang7d235f42015-07-16 20:19:45 +080060
lijuang4ece1e72015-08-14 21:02:36 +080061#define ORANGE_WARNING_MSG "Your device has been unlocker and cann't "\
62 "be trusted\n\nTo learn more, visit:\n"
lijuang7d235f42015-07-16 20:19:45 +080063
lijuang4ece1e72015-08-14 21:02:36 +080064#define RED_WARNING_MSG "Your device has failed verification and may "\
65 "not work properly\n\nTo learn more, visit:\n"
lijuang7d235f42015-07-16 20:19:45 +080066
67static bool is_thread_start = false;
68struct select_msg_info msg_info;
69
lijuang4ece1e72015-08-14 21:02:36 +080070#if VERIFIED_BOOT
71struct boot_verify_info {
72 int msg_type;
73 const char *warning_msg;
74};
75
76struct boot_verify_info boot_verify_info[] = {
77 [DISPLAY_MENU_RED] = {FBCON_RED_MSG, RED_WARNING_MSG},
78 [DISPLAY_MENU_YELLOW] = {FBCON_YELLOW_MSG, YELLOW_WARNING_MSG},
79 [DISPLAY_MENU_ORANGE] = {FBCON_ORANGE_MSG, ORANGE_WARNING_MSG}};
80#endif
81
82static char *verify_option_menu[] = {
lijuang7d235f42015-07-16 20:19:45 +080083 [POWEROFF] = "Power off\n",
84 [RESTART] = "Restart\n",
85 [RECOVER] = "Recovery\n",
86 [FASTBOOT] = "Fastboot\n",
87 [BACK] = "Back to previous page\n"};
88
lijuang4ece1e72015-08-14 21:02:36 +080089static char *fastboot_option_menu[] = {
90 [0] = "START\n",
91 [1] = "Restart bootloader\n",
92 [2] = "Recovery mode\n",
93 [3] = "Power off\n"};
94
lijuang7d235f42015-07-16 20:19:45 +080095static int big_factor = 2;
96static int common_factor = 1;
97
98void wait_for_users_action()
99{
100 struct select_msg_info *select_msg;
101 select_msg = &msg_info;
102
103 while(1) {
104 if (select_msg->msg_timeout == true &&
105 select_msg->msg_volume_key_pressed == false)
106 break;
107 if (select_msg->msg_power_key_pressed == true)
108 break;
109
110 thread_sleep(10);
111 }
112 fbcon_clear();
113 display_image_on_screen();
114}
115
116static void set_message_factor()
117{
118 uint32_t tmp_factor = 0;
119 uint32_t max_x_count = 40;
120 uint32_t max_x = fbcon_get_max_x();
121
122 max_x = fbcon_get_max_x();
123 tmp_factor = max_x/max_x_count;
124
125 if(tmp_factor <= 1) {
126 big_factor = 2;
127 common_factor = 1;
128 } else {
129 big_factor = tmp_factor*2;
130 common_factor = tmp_factor;
131 }
132}
133
134static void display_fbcon_menu_message(char *str, unsigned type,
135 unsigned scale_factor)
136{
137 while(*str != 0) {
138 fbcon_putc_factor(*str++, type, scale_factor);
139 }
140}
141
142static char *str_align_right(char *str, int factor)
143{
144 uint32_t max_x = 0;
145 int diff = 0;
146 int i = 0;
147 char *str_target = NULL;
148
149 max_x = fbcon_get_max_x();
150 if (!str_target && max_x) {
151 str_target = malloc(max_x);
152 }
153
154 if (str_target) {
155 memset(str_target, 0, max_x);
156 if ( max_x/factor > strlen(str)) {
157 if (factor == 1)
158 diff = max_x/factor - strlen(str) - 1;
159 else
160 diff = max_x/factor - strlen(str);
161 for (i = 0; i < diff; i++) {
162 strcat(str_target, " ");
163 }
164 strcat(str_target, str);
165 return str_target;
166 } else {
167 free(str_target);
168 return str;
169 }
170 }
171 return str;
172}
173
lijuang4ece1e72015-08-14 21:02:36 +0800174void display_unlock_menu(struct select_msg_info *unlock_msg_info, int type)
lijuang7d235f42015-07-16 20:19:45 +0800175{
176 fbcon_clear();
177 memset(unlock_msg_info, 0, sizeof(struct select_msg_info));
178 display_fbcon_menu_message("Unlock bootloader?\n",
179 FBCON_UNLOCK_TITLE_MSG, big_factor);
lijuang4ece1e72015-08-14 21:02:36 +0800180 fbcon_draw_line(FBCON_COMMON_MSG);
lijuang7d235f42015-07-16 20:19:45 +0800181
lijuang4ece1e72015-08-14 21:02:36 +0800182 display_fbcon_menu_message((char*)unlock_menu_common_msg,
lijuang7d235f42015-07-16 20:19:45 +0800183 FBCON_COMMON_MSG, common_factor);
lijuang4ece1e72015-08-14 21:02:36 +0800184 fbcon_draw_line(FBCON_COMMON_MSG);
lijuang7d235f42015-07-16 20:19:45 +0800185 unlock_msg_info->option_start[0] = fbcon_get_current_line();
186 display_fbcon_menu_message("Yes\n",
187 FBCON_COMMON_MSG, big_factor);
188 unlock_msg_info->option_bg[0] = fbcon_get_current_bg();
189 display_fbcon_menu_message("Unlock bootloader(may void warranty)\n",
190 FBCON_COMMON_MSG, common_factor);
191 unlock_msg_info->option_end[0] = fbcon_get_current_line();
lijuang4ece1e72015-08-14 21:02:36 +0800192 fbcon_draw_line(FBCON_COMMON_MSG);
lijuang7d235f42015-07-16 20:19:45 +0800193 unlock_msg_info->option_start[1] = fbcon_get_current_line();
194 display_fbcon_menu_message("No\n",
195 FBCON_COMMON_MSG, big_factor);
196 unlock_msg_info->option_bg[1] = fbcon_get_current_bg();
197 display_fbcon_menu_message("Do not unlock bootloader and restart phone\n",
198 FBCON_COMMON_MSG, common_factor);
199 unlock_msg_info->option_end[1] = fbcon_get_current_line();
lijuang4ece1e72015-08-14 21:02:36 +0800200 fbcon_draw_line(FBCON_COMMON_MSG);
lijuang7d235f42015-07-16 20:19:45 +0800201
lijuang4ece1e72015-08-14 21:02:36 +0800202 if (type == UNLOCK)
203 unlock_msg_info->msg_type = DISPLAY_MENU_UNLOCK;
204 else if (type == UNLOCK_CRITICAL)
205 unlock_msg_info->msg_type = DISPLAY_MENU_UNLOCK_CRITICAL;
206
207 unlock_msg_info->option_num = 2;
lijuang7d235f42015-07-16 20:19:45 +0800208}
209
lijuang4ece1e72015-08-14 21:02:36 +0800210#if VERIFIED_BOOT
lijuang7d235f42015-07-16 20:19:45 +0800211void display_boot_verified_menu(struct select_msg_info *msg_info, int type)
212{
lijuang7d235f42015-07-16 20:19:45 +0800213 unsigned char* fp_buf = NULL;
214 char fp_str_temp[EVP_MAX_MD_SIZE] = {'\0'};
215 char fp_str[EVP_MAX_MD_SIZE*2] = {'\0'};
216 char str_temp[8];
217
218 char str1[]= "Start >";
219 char str2[] = "Continue boot";
220 char *str_target = NULL;
221 uint32 fp_size = 0;
222 unsigned int i = 0;
223
224 fbcon_clear();
225 memset(msg_info, 0, sizeof(struct select_msg_info));
226
lijuang7d235f42015-07-16 20:19:45 +0800227 /* Align Right */
228 str_target = str_align_right(str1, big_factor);
Sridhar Parasuram995a3552015-08-22 08:46:10 -0700229 if(str_target != NULL)
230 display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, big_factor);
lijuang7d235f42015-07-16 20:19:45 +0800231
232 str_target = str_align_right(str2, common_factor);
Sridhar Parasuram995a3552015-08-22 08:46:10 -0700233 if(str_target != NULL)
234 display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, common_factor);
lijuang7d235f42015-07-16 20:19:45 +0800235
236 display_fbcon_menu_message("\n< More options\n",
237 FBCON_COMMON_MSG, common_factor);
238 display_fbcon_menu_message("press VOLUME keys\n\n",
239 FBCON_SUBTITLE_MSG, common_factor);
lijuang4ece1e72015-08-14 21:02:36 +0800240 if(boot_verify_info[type].warning_msg != NULL)
241 display_fbcon_menu_message((char*)boot_verify_info[type].warning_msg,
242 FBCON_COMMON_MSG, common_factor);
lijuang7d235f42015-07-16 20:19:45 +0800243
244 display_fbcon_menu_message("g.co/placeholder\n",
lijuang4ece1e72015-08-14 21:02:36 +0800245 boot_verify_info[type].msg_type, common_factor);
lijuang7d235f42015-07-16 20:19:45 +0800246
lijuang7d235f42015-07-16 20:19:45 +0800247 if (type == DISPLAY_MENU_YELLOW) {
248 fp_buf = get_boot_fingerprint(&fp_size);
249 if (fp_buf != NULL) {
250 strncpy(fp_str_temp, (char const *)fp_buf, fp_size);
251 for (i = 0; i < fp_size; i++) {
252 if(i == fp_size - 1)
253 sprintf(str_temp, "%02x", fp_str_temp[i]);
254 else
255 sprintf(str_temp, "%02x-", fp_str_temp[i]);
256
257 strcat(fp_str, str_temp);
258 }
259 }
260 display_fbcon_menu_message("ID:", FBCON_COMMON_MSG, common_factor);
261 display_fbcon_menu_message(fp_str, FBCON_COMMON_MSG, common_factor);
262 }
lijuang7d235f42015-07-16 20:19:45 +0800263
264 display_fbcon_menu_message("\n\nIf no key pressed:\n"\
265 "Your device will boot in 5 seconds\n\n", FBCON_COMMON_MSG, common_factor);
266
267 msg_info->msg_type = type;
268 if(str_target) {
269 free(str_target);
270 }
271}
lijuang4ece1e72015-08-14 21:02:36 +0800272#endif
lijuang7d235f42015-07-16 20:19:45 +0800273
274void display_boot_verified_option(struct select_msg_info *msg_info)
275{
276 int i = 0;
lijuang4ece1e72015-08-14 21:02:36 +0800277 int len = 0;
lijuang7d235f42015-07-16 20:19:45 +0800278 fbcon_clear();
279 memset(msg_info, 0, sizeof(struct select_msg_info));
280
lijuang4ece1e72015-08-14 21:02:36 +0800281 len = ARRAY_SIZE(verify_option_menu);
lijuang7d235f42015-07-16 20:19:45 +0800282 display_fbcon_menu_message("Options menu:\n\n",
283 FBCON_COMMON_MSG, big_factor);
284 display_fbcon_menu_message("Press volume key to select, and "\
285 "press power key to select\n\n", FBCON_COMMON_MSG, common_factor);
286
lijuang4ece1e72015-08-14 21:02:36 +0800287 for (i = 0; i < len; i++) {
288 fbcon_draw_line(FBCON_COMMON_MSG);
lijuang7d235f42015-07-16 20:19:45 +0800289 msg_info->option_start[i] = fbcon_get_current_line();
lijuang4ece1e72015-08-14 21:02:36 +0800290 display_fbcon_menu_message(verify_option_menu[i],
lijuang7d235f42015-07-16 20:19:45 +0800291 FBCON_COMMON_MSG, common_factor);
292 msg_info->option_bg[i]= fbcon_get_current_bg();
293 msg_info->option_end[i]= fbcon_get_current_line();
294 }
295
lijuang4ece1e72015-08-14 21:02:36 +0800296 fbcon_draw_line(FBCON_COMMON_MSG);
lijuang7d235f42015-07-16 20:19:45 +0800297 msg_info->msg_type = DISPLAY_MENU_MORE_OPTION;
lijuang4ece1e72015-08-14 21:02:36 +0800298 msg_info->option_num = len;
299}
300
301void display_fastboot_menu(struct select_msg_info *fastboot_msg_info,
302 int option_index)
303{
304 int len;
305 int msg_type = FBCON_COMMON_MSG;
306 char msg_buf[64];
307 char msg[128];
308
309 fbcon_clear();
310 memset(fastboot_msg_info, 0, sizeof(struct select_msg_info));
311
312 len = ARRAY_SIZE(fastboot_option_menu);
313 switch(option_index) {
314 case 0:
315 msg_type = FBCON_GREEN_MSG;
316 break;
317 case 1:
318 case 2:
319 msg_type = FBCON_RED_MSG;
320 break;
321 case 3:
322 msg_type = FBCON_COMMON_MSG;
323 break;
324 }
325 fbcon_draw_line(msg_type);
326 display_fbcon_menu_message(fastboot_option_menu[option_index],
327 msg_type, big_factor);
328 fbcon_draw_line(msg_type);
329 display_fbcon_menu_message("\n\nPress volume key to select, and "\
330 "press power key to select\n\n", FBCON_COMMON_MSG, common_factor);
331
332 display_fbcon_menu_message("FASTBOOT MODE\n", FBCON_RED_MSG, common_factor);
333
334 get_product_name((unsigned char *) msg_buf);
335 snprintf(msg, sizeof(msg), "PRODUCT_NAME - %s\n", msg_buf);
336 display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
337
338 memset(msg_buf, 0, sizeof(msg_buf));
339 smem_get_hw_platform_name((unsigned char *) msg_buf, sizeof(msg_buf));
340 snprintf(msg, sizeof(msg), "VARIANT - %s %s\n",
341 msg_buf, target_is_emmc_boot()? "eMMC":"UFS");
342 display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
343
344 memset(msg_buf, 0, sizeof(msg_buf));
345 get_bootloader_version((unsigned char *) msg_buf);
346 snprintf(msg, sizeof(msg), "BOOTLOADER VERSION - %s\n",
347 msg_buf);
348 display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
349
350 memset(msg_buf, 0, sizeof(msg_buf));
351 get_baseband_version((unsigned char *) msg_buf);
352 snprintf(msg, sizeof(msg), "BASEBAND VERSION - %s\n",
353 msg_buf);
354 display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
355
356 memset(msg_buf, 0, sizeof(msg_buf));
357 target_serialno((unsigned char *) msg_buf);
358 snprintf(msg, sizeof(msg), "SERIAL NUMBER - %s\n", msg_buf);
359 display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
360
361 snprintf(msg, sizeof(msg), "SECURE BOOT - %s\n",
362 is_secure_boot_enable()? "enabled":"disabled");
363 display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
364
365 snprintf(msg, sizeof(msg), "DEVICE STATE - %s\n",
366 is_device_locked()? "locked":"unlocked");
367 display_fbcon_menu_message(msg, FBCON_RED_MSG, common_factor);
368
369 fastboot_msg_info->msg_type = DISPLAY_MENU_FASTBOOT;
370 fastboot_msg_info->option_num = len;
lijuang7d235f42015-07-16 20:19:45 +0800371}
372
373static void display_menu_thread_start(struct select_msg_info *msg_info)
374{
375 thread_t *thr;
376
377 if (!is_thread_start) {
378 thr = thread_create("selectkeydetect", &select_msg_keys_detect,
379 (void*)msg_info, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
380 if (!thr) {
381 dprintf(CRITICAL, "ERROR: creat device status detect thread failed!!\n");
382 return;
383 }
384 thread_resume(thr);
385 }
386
387 is_thread_start = true;
388}
389
lijuang4ece1e72015-08-14 21:02:36 +0800390void display_unlock_menu_thread(int type)
lijuang7d235f42015-07-16 20:19:45 +0800391{
lijuang4ece1e72015-08-14 21:02:36 +0800392 struct select_msg_info *unlock_menu_msg_info;
393 unlock_menu_msg_info = &msg_info;
lijuang7d235f42015-07-16 20:19:45 +0800394
395 set_message_factor();
lijuang4ece1e72015-08-14 21:02:36 +0800396 display_unlock_menu(unlock_menu_msg_info, type);
lijuang7d235f42015-07-16 20:19:45 +0800397
lijuang4ece1e72015-08-14 21:02:36 +0800398 dprintf(INFO, "creating unlock keys detect thread\n");
399 display_menu_thread_start(unlock_menu_msg_info);
lijuang7d235f42015-07-16 20:19:45 +0800400}
401
lijuang4ece1e72015-08-14 21:02:36 +0800402void display_fastboot_menu_thread()
403{
404 struct select_msg_info *fastboot_menu_msg_info;
405 fastboot_menu_msg_info = &msg_info;
406
407 set_message_factor();
408 display_fastboot_menu(fastboot_menu_msg_info, 0);
409
410 dprintf(INFO, "creating fastboot menu keys detect thread\n");
411 display_menu_thread_start(fastboot_menu_msg_info);
412}
413
414#if VERIFIED_BOOT
415void display_bootverify_menu_thread(int type)
416{
417 struct select_msg_info *bootverify_menu_msg_info;
418 bootverify_menu_msg_info = &msg_info;
419
420 set_message_factor();
421 display_boot_verified_menu(bootverify_menu_msg_info, type);
422
423 dprintf(INFO, "creating boot verify keys detect thread\n");
424 display_menu_thread_start(bootverify_menu_msg_info);
425}
426#endif