blob: 895db07a774a6fc02c8273acd2e05df29528864f [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>
40
41#define UNLOCK_OPTION_NUM 2
42#define BOOT_VERIFY_OPTION_NUM 5
43
44static char *unlock_menu_common_msg = "If you unlock the bootloader, "\
45 "you will be able to install "\
46 "custom operating system on this phone.\n\n"\
47 "A custom OS is not subject to the same testing "\
48 "as the original OS, "\
49 "and can cause your phone and installed "\
50 "applications to stop working properly.\n\n"\
51 "To prevent unauthorized access to your personal data, "\
52 "unlocking the bootloader will also delete all personal "\
53 "data from your phone(a \"fatory data reset\").\n\n"\
54 "Press the Volume Up/Down buttons to select Yes "\
55 "or No. Then press the Power button to continue.\n";
56
57static char *yellow_warning_msg = "Your device has loaded a diffrent operating "\
58 "system\n\nTo learn more, visit:\n";
59
60static char *orange_warning_msg = "Your device has been unlocker and cann't "\
61 "be trusted\n\nTo learn more, visit:\n";
62
63static char *red_warning_msg = "Your device has failed verification and may "\
64 "not work properly\n\nTo learn more, visit:\n";
65
66static bool is_thread_start = false;
67struct select_msg_info msg_info;
68
69static char *option_menu[] = {
70 [POWEROFF] = "Power off\n",
71 [RESTART] = "Restart\n",
72 [RECOVER] = "Recovery\n",
73 [FASTBOOT] = "Fastboot\n",
74 [BACK] = "Back to previous page\n"};
75
76static int big_factor = 2;
77static int common_factor = 1;
78
79void wait_for_users_action()
80{
81 struct select_msg_info *select_msg;
82 select_msg = &msg_info;
83
84 while(1) {
85 if (select_msg->msg_timeout == true &&
86 select_msg->msg_volume_key_pressed == false)
87 break;
88 if (select_msg->msg_power_key_pressed == true)
89 break;
90
91 thread_sleep(10);
92 }
93 fbcon_clear();
94 display_image_on_screen();
95}
96
97static void set_message_factor()
98{
99 uint32_t tmp_factor = 0;
100 uint32_t max_x_count = 40;
101 uint32_t max_x = fbcon_get_max_x();
102
103 max_x = fbcon_get_max_x();
104 tmp_factor = max_x/max_x_count;
105
106 if(tmp_factor <= 1) {
107 big_factor = 2;
108 common_factor = 1;
109 } else {
110 big_factor = tmp_factor*2;
111 common_factor = tmp_factor;
112 }
113}
114
115static void display_fbcon_menu_message(char *str, unsigned type,
116 unsigned scale_factor)
117{
118 while(*str != 0) {
119 fbcon_putc_factor(*str++, type, scale_factor);
120 }
121}
122
123static char *str_align_right(char *str, int factor)
124{
125 uint32_t max_x = 0;
126 int diff = 0;
127 int i = 0;
128 char *str_target = NULL;
129
130 max_x = fbcon_get_max_x();
131 if (!str_target && max_x) {
132 str_target = malloc(max_x);
133 }
134
135 if (str_target) {
136 memset(str_target, 0, max_x);
137 if ( max_x/factor > strlen(str)) {
138 if (factor == 1)
139 diff = max_x/factor - strlen(str) - 1;
140 else
141 diff = max_x/factor - strlen(str);
142 for (i = 0; i < diff; i++) {
143 strcat(str_target, " ");
144 }
145 strcat(str_target, str);
146 return str_target;
147 } else {
148 free(str_target);
149 return str;
150 }
151 }
152 return str;
153}
154
155void display_unlock_menu(struct select_msg_info *unlock_msg_info)
156{
157 fbcon_clear();
158 memset(unlock_msg_info, 0, sizeof(struct select_msg_info));
159 display_fbcon_menu_message("Unlock bootloader?\n",
160 FBCON_UNLOCK_TITLE_MSG, big_factor);
161 fbcon_draw_line();
162
163 display_fbcon_menu_message(unlock_menu_common_msg,
164 FBCON_COMMON_MSG, common_factor);
165 fbcon_draw_line();
166 unlock_msg_info->option_start[0] = fbcon_get_current_line();
167 display_fbcon_menu_message("Yes\n",
168 FBCON_COMMON_MSG, big_factor);
169 unlock_msg_info->option_bg[0] = fbcon_get_current_bg();
170 display_fbcon_menu_message("Unlock bootloader(may void warranty)\n",
171 FBCON_COMMON_MSG, common_factor);
172 unlock_msg_info->option_end[0] = fbcon_get_current_line();
173 fbcon_draw_line();
174 unlock_msg_info->option_start[1] = fbcon_get_current_line();
175 display_fbcon_menu_message("No\n",
176 FBCON_COMMON_MSG, big_factor);
177 unlock_msg_info->option_bg[1] = fbcon_get_current_bg();
178 display_fbcon_menu_message("Do not unlock bootloader and restart phone\n",
179 FBCON_COMMON_MSG, common_factor);
180 unlock_msg_info->option_end[1] = fbcon_get_current_line();
181 fbcon_draw_line();
182
183 unlock_msg_info->msg_type = DISPLAY_MENU_UNLOCK;
184 unlock_msg_info->option_num = UNLOCK_OPTION_NUM;
185}
186
187void display_boot_verified_menu(struct select_msg_info *msg_info, int type)
188{
189 int msg_type = FBCON_COMMON_MSG;
190 char *warning_msg = NULL;
191 unsigned char* fp_buf = NULL;
192 char fp_str_temp[EVP_MAX_MD_SIZE] = {'\0'};
193 char fp_str[EVP_MAX_MD_SIZE*2] = {'\0'};
194 char str_temp[8];
195
196 char str1[]= "Start >";
197 char str2[] = "Continue boot";
198 char *str_target = NULL;
199 uint32 fp_size = 0;
200 unsigned int i = 0;
201
202 fbcon_clear();
203 memset(msg_info, 0, sizeof(struct select_msg_info));
204
205 switch (type) {
206 case DISPLAY_MENU_RED:
207 msg_type = FBCON_RED_MSG;
208 warning_msg = red_warning_msg;
209 break;
210 case DISPLAY_MENU_YELLOW:
211 msg_type = FBCON_YELLOW_MSG;
212 warning_msg = yellow_warning_msg;
213 break;
214 case DISPLAY_MENU_ORANGE:
215 msg_type = FBCON_ORANGE_MSG;
216 warning_msg = orange_warning_msg;
217 break;
218 }
219
220 /* Align Right */
221 str_target = str_align_right(str1, big_factor);
Sridhar Parasuram995a3552015-08-22 08:46:10 -0700222 if(str_target != NULL)
223 display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, big_factor);
lijuang7d235f42015-07-16 20:19:45 +0800224
225 str_target = str_align_right(str2, common_factor);
Sridhar Parasuram995a3552015-08-22 08:46:10 -0700226 if(str_target != NULL)
227 display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, common_factor);
lijuang7d235f42015-07-16 20:19:45 +0800228
229 display_fbcon_menu_message("\n< More options\n",
230 FBCON_COMMON_MSG, common_factor);
231 display_fbcon_menu_message("press VOLUME keys\n\n",
232 FBCON_SUBTITLE_MSG, common_factor);
Sridhar Parasuram995a3552015-08-22 08:46:10 -0700233 if(warning_msg != NULL)
234 display_fbcon_menu_message(warning_msg, FBCON_COMMON_MSG, common_factor);
lijuang7d235f42015-07-16 20:19:45 +0800235
236 display_fbcon_menu_message("g.co/placeholder\n",
237 msg_type, common_factor);
238
239#if VERIFIED_BOOT
240 if (type == DISPLAY_MENU_YELLOW) {
241 fp_buf = get_boot_fingerprint(&fp_size);
242 if (fp_buf != NULL) {
243 strncpy(fp_str_temp, (char const *)fp_buf, fp_size);
244 for (i = 0; i < fp_size; i++) {
245 if(i == fp_size - 1)
246 sprintf(str_temp, "%02x", fp_str_temp[i]);
247 else
248 sprintf(str_temp, "%02x-", fp_str_temp[i]);
249
250 strcat(fp_str, str_temp);
251 }
252 }
253 display_fbcon_menu_message("ID:", FBCON_COMMON_MSG, common_factor);
254 display_fbcon_menu_message(fp_str, FBCON_COMMON_MSG, common_factor);
255 }
256#endif
257
258 display_fbcon_menu_message("\n\nIf no key pressed:\n"\
259 "Your device will boot in 5 seconds\n\n", FBCON_COMMON_MSG, common_factor);
260
261 msg_info->msg_type = type;
262 if(str_target) {
263 free(str_target);
264 }
265}
266
267void display_boot_verified_option(struct select_msg_info *msg_info)
268{
269 int i = 0;
270 fbcon_clear();
271 memset(msg_info, 0, sizeof(struct select_msg_info));
272
273 display_fbcon_menu_message("Options menu:\n\n",
274 FBCON_COMMON_MSG, big_factor);
275 display_fbcon_menu_message("Press volume key to select, and "\
276 "press power key to select\n\n", FBCON_COMMON_MSG, common_factor);
277
278 for (i = 0; i < BOOT_VERIFY_OPTION_NUM; i++) {
279 fbcon_draw_line();
280 msg_info->option_start[i] = fbcon_get_current_line();
281 display_fbcon_menu_message(option_menu[i],
282 FBCON_COMMON_MSG, common_factor);
283 msg_info->option_bg[i]= fbcon_get_current_bg();
284 msg_info->option_end[i]= fbcon_get_current_line();
285 }
286
287 fbcon_draw_line();
288 msg_info->msg_type = DISPLAY_MENU_MORE_OPTION;
289 msg_info->option_num = BOOT_VERIFY_OPTION_NUM;
290}
291
292static void display_menu_thread_start(struct select_msg_info *msg_info)
293{
294 thread_t *thr;
295
296 if (!is_thread_start) {
297 thr = thread_create("selectkeydetect", &select_msg_keys_detect,
298 (void*)msg_info, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
299 if (!thr) {
300 dprintf(CRITICAL, "ERROR: creat device status detect thread failed!!\n");
301 return;
302 }
303 thread_resume(thr);
304 }
305
306 is_thread_start = true;
307}
308
309void display_menu_thread(int type)
310{
311 struct select_msg_info *display_menu_msg_info;
312 display_menu_msg_info = &msg_info;
313 int menu_type = 0;
314
315 set_message_factor();
316 if (type == DISPLAY_THREAD_UNLOCK) {
317 display_unlock_menu(display_menu_msg_info);
318
319 dprintf(INFO, "creating oem unlock keys detect thread\n");
320 display_menu_thread_start(display_menu_msg_info);
321 } else {
322 #if VERIFIED_BOOT
323 if (boot_verify_get_state() == ORANGE) {
324 menu_type = DISPLAY_MENU_ORANGE;
325 } else if (boot_verify_get_state() == YELLOW) {
326 menu_type = DISPLAY_MENU_YELLOW;
327 } else if (boot_verify_get_state() == RED) {
328 menu_type = DISPLAY_MENU_RED;
329 }
330 display_boot_verified_menu(display_menu_msg_info, menu_type);
331
332 dprintf(INFO, "creating device state keys detect thread\n");
333 display_menu_thread_start(display_menu_msg_info);
334
335 #else
336 dprintf(CRITICAL, "VERIFIED_BOOT is not enable!!\n");
337 return;
338 #endif
339 }
340}
341