blob: 2a792b28bcba966e1022fd1c87bc254b3ee105a8 [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);
222 display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, big_factor);
223
224 str_target = str_align_right(str2, common_factor);
225 display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, common_factor);
226
227 display_fbcon_menu_message("\n< More options\n",
228 FBCON_COMMON_MSG, common_factor);
229 display_fbcon_menu_message("press VOLUME keys\n\n",
230 FBCON_SUBTITLE_MSG, common_factor);
231
232 display_fbcon_menu_message(warning_msg, FBCON_COMMON_MSG, common_factor);
233
234 display_fbcon_menu_message("g.co/placeholder\n",
235 msg_type, common_factor);
236
237#if VERIFIED_BOOT
238 if (type == DISPLAY_MENU_YELLOW) {
239 fp_buf = get_boot_fingerprint(&fp_size);
240 if (fp_buf != NULL) {
241 strncpy(fp_str_temp, (char const *)fp_buf, fp_size);
242 for (i = 0; i < fp_size; i++) {
243 if(i == fp_size - 1)
244 sprintf(str_temp, "%02x", fp_str_temp[i]);
245 else
246 sprintf(str_temp, "%02x-", fp_str_temp[i]);
247
248 strcat(fp_str, str_temp);
249 }
250 }
251 display_fbcon_menu_message("ID:", FBCON_COMMON_MSG, common_factor);
252 display_fbcon_menu_message(fp_str, FBCON_COMMON_MSG, common_factor);
253 }
254#endif
255
256 display_fbcon_menu_message("\n\nIf no key pressed:\n"\
257 "Your device will boot in 5 seconds\n\n", FBCON_COMMON_MSG, common_factor);
258
259 msg_info->msg_type = type;
260 if(str_target) {
261 free(str_target);
262 }
263}
264
265void display_boot_verified_option(struct select_msg_info *msg_info)
266{
267 int i = 0;
268 fbcon_clear();
269 memset(msg_info, 0, sizeof(struct select_msg_info));
270
271 display_fbcon_menu_message("Options menu:\n\n",
272 FBCON_COMMON_MSG, big_factor);
273 display_fbcon_menu_message("Press volume key to select, and "\
274 "press power key to select\n\n", FBCON_COMMON_MSG, common_factor);
275
276 for (i = 0; i < BOOT_VERIFY_OPTION_NUM; i++) {
277 fbcon_draw_line();
278 msg_info->option_start[i] = fbcon_get_current_line();
279 display_fbcon_menu_message(option_menu[i],
280 FBCON_COMMON_MSG, common_factor);
281 msg_info->option_bg[i]= fbcon_get_current_bg();
282 msg_info->option_end[i]= fbcon_get_current_line();
283 }
284
285 fbcon_draw_line();
286 msg_info->msg_type = DISPLAY_MENU_MORE_OPTION;
287 msg_info->option_num = BOOT_VERIFY_OPTION_NUM;
288}
289
290static void display_menu_thread_start(struct select_msg_info *msg_info)
291{
292 thread_t *thr;
293
294 if (!is_thread_start) {
295 thr = thread_create("selectkeydetect", &select_msg_keys_detect,
296 (void*)msg_info, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
297 if (!thr) {
298 dprintf(CRITICAL, "ERROR: creat device status detect thread failed!!\n");
299 return;
300 }
301 thread_resume(thr);
302 }
303
304 is_thread_start = true;
305}
306
307void display_menu_thread(int type)
308{
309 struct select_msg_info *display_menu_msg_info;
310 display_menu_msg_info = &msg_info;
311 int menu_type = 0;
312
313 set_message_factor();
314 if (type == DISPLAY_THREAD_UNLOCK) {
315 display_unlock_menu(display_menu_msg_info);
316
317 dprintf(INFO, "creating oem unlock keys detect thread\n");
318 display_menu_thread_start(display_menu_msg_info);
319 } else {
320 #if VERIFIED_BOOT
321 if (boot_verify_get_state() == ORANGE) {
322 menu_type = DISPLAY_MENU_ORANGE;
323 } else if (boot_verify_get_state() == YELLOW) {
324 menu_type = DISPLAY_MENU_YELLOW;
325 } else if (boot_verify_get_state() == RED) {
326 menu_type = DISPLAY_MENU_RED;
327 }
328 display_boot_verified_menu(display_menu_msg_info, menu_type);
329
330 dprintf(INFO, "creating device state keys detect thread\n");
331 display_menu_thread_start(display_menu_msg_info);
332
333 #else
334 dprintf(CRITICAL, "VERIFIED_BOOT is not enable!!\n");
335 return;
336 #endif
337 }
338}
339