blob: bb988dfb6da3139960e5ec0a8448f5b768fdb9a6 [file] [log] [blame]
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <debug.h>
#include <reg.h>
#include <stdlib.h>
#include <openssl/evp.h>
#include <dev/fbcon.h>
#include <kernel/thread.h>
#include <display_menu.h>
#include <menu_keys_detect.h>
#include <boot_verifier.h>
#include <string.h>
#include <platform.h>
#include <smem.h>
#include <target.h>
#include <sys/types.h>
#include <../../../app/aboot/devinfo.h>
static const char *unlock_menu_common_msg = "If you unlock the bootloader, "\
"you will be able to install "\
"custom operating system on this phone.\n\n"\
"A custom OS is not subject to the same testing "\
"as the original OS, "\
"and can cause your phone and installed "\
"applications to stop working properly.\n\n"\
"To prevent unauthorized access to your personal data, "\
"unlocking the bootloader will also delete all personal "\
"data from your phone(a \"fatory data reset\").\n\n"\
"Press the Volume Up/Down buttons to select Yes "\
"or No. Then press the Power button to continue.\n";
#define YELLOW_WARNING_MSG "Your device has loaded a diffrent operating "\
"system\n\nTo learn more, visit:\n"
#define ORANGE_WARNING_MSG "Your device has been unlocker and cann't "\
"be trusted\n\nTo learn more, visit:\n"
#define RED_WARNING_MSG "Your device has failed verification and may "\
"not work properly\n\nTo learn more, visit:\n"
static bool is_thread_start = false;
struct select_msg_info msg_info;
#if VERIFIED_BOOT
struct boot_verify_info {
int msg_type;
const char *warning_msg;
};
struct boot_verify_info boot_verify_info[] = {
[DISPLAY_MENU_RED] = {FBCON_RED_MSG, RED_WARNING_MSG},
[DISPLAY_MENU_YELLOW] = {FBCON_YELLOW_MSG, YELLOW_WARNING_MSG},
[DISPLAY_MENU_ORANGE] = {FBCON_ORANGE_MSG, ORANGE_WARNING_MSG}};
#endif
static char *verify_option_menu[] = {
[POWEROFF] = "Power off\n",
[RESTART] = "Restart\n",
[RECOVER] = "Recovery\n",
[FASTBOOT] = "Fastboot\n",
[BACK] = "Back to previous page\n"};
static char *fastboot_option_menu[] = {
[0] = "START\n",
[1] = "Restart bootloader\n",
[2] = "Recovery mode\n",
[3] = "Power off\n"};
static int big_factor = 2;
static int common_factor = 1;
void wait_for_users_action()
{
struct select_msg_info *select_msg;
select_msg = &msg_info;
while(1) {
if (select_msg->msg_timeout == true &&
select_msg->msg_volume_key_pressed == false)
break;
if (select_msg->msg_power_key_pressed == true)
break;
thread_sleep(10);
}
fbcon_clear();
display_image_on_screen();
}
static void set_message_factor()
{
uint32_t tmp_factor = 0;
uint32_t max_x_count = 40;
uint32_t max_x = fbcon_get_max_x();
max_x = fbcon_get_max_x();
tmp_factor = max_x/max_x_count;
if(tmp_factor <= 1) {
big_factor = 2;
common_factor = 1;
} else {
big_factor = tmp_factor*2;
common_factor = tmp_factor;
}
}
static void display_fbcon_menu_message(char *str, unsigned type,
unsigned scale_factor)
{
while(*str != 0) {
fbcon_putc_factor(*str++, type, scale_factor);
}
}
static char *str_align_right(char *str, int factor)
{
uint32_t max_x = 0;
int diff = 0;
int i = 0;
char *str_target = NULL;
max_x = fbcon_get_max_x();
if (!str_target && max_x) {
str_target = malloc(max_x);
}
if (str_target) {
memset(str_target, 0, max_x);
if ( max_x/factor > strlen(str)) {
if (factor == 1)
diff = max_x/factor - strlen(str) - 1;
else
diff = max_x/factor - strlen(str);
for (i = 0; i < diff; i++) {
strcat(str_target, " ");
}
strcat(str_target, str);
return str_target;
} else {
free(str_target);
return str;
}
}
return str;
}
void display_unlock_menu(struct select_msg_info *unlock_msg_info, int type)
{
fbcon_clear();
memset(unlock_msg_info, 0, sizeof(struct select_msg_info));
display_fbcon_menu_message("Unlock bootloader?\n",
FBCON_UNLOCK_TITLE_MSG, big_factor);
fbcon_draw_line(FBCON_COMMON_MSG);
display_fbcon_menu_message((char*)unlock_menu_common_msg,
FBCON_COMMON_MSG, common_factor);
fbcon_draw_line(FBCON_COMMON_MSG);
unlock_msg_info->option_start[0] = fbcon_get_current_line();
display_fbcon_menu_message("Yes\n",
FBCON_COMMON_MSG, big_factor);
unlock_msg_info->option_bg[0] = fbcon_get_current_bg();
display_fbcon_menu_message("Unlock bootloader(may void warranty)\n",
FBCON_COMMON_MSG, common_factor);
unlock_msg_info->option_end[0] = fbcon_get_current_line();
fbcon_draw_line(FBCON_COMMON_MSG);
unlock_msg_info->option_start[1] = fbcon_get_current_line();
display_fbcon_menu_message("No\n",
FBCON_COMMON_MSG, big_factor);
unlock_msg_info->option_bg[1] = fbcon_get_current_bg();
display_fbcon_menu_message("Do not unlock bootloader and restart phone\n",
FBCON_COMMON_MSG, common_factor);
unlock_msg_info->option_end[1] = fbcon_get_current_line();
fbcon_draw_line(FBCON_COMMON_MSG);
if (type == UNLOCK)
unlock_msg_info->msg_type = DISPLAY_MENU_UNLOCK;
else if (type == UNLOCK_CRITICAL)
unlock_msg_info->msg_type = DISPLAY_MENU_UNLOCK_CRITICAL;
unlock_msg_info->option_num = 2;
}
#if VERIFIED_BOOT
void display_boot_verified_menu(struct select_msg_info *msg_info, int type)
{
unsigned char* fp_buf = NULL;
char fp_str_temp[EVP_MAX_MD_SIZE] = {'\0'};
char fp_str[EVP_MAX_MD_SIZE*2] = {'\0'};
char str_temp[8];
char str1[]= "Start >";
char str2[] = "Continue boot";
char *str_target = NULL;
uint32 fp_size = 0;
unsigned int i = 0;
fbcon_clear();
memset(msg_info, 0, sizeof(struct select_msg_info));
/* Align Right */
str_target = str_align_right(str1, big_factor);
if(str_target != NULL)
display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, big_factor);
str_target = str_align_right(str2, common_factor);
if(str_target != NULL)
display_fbcon_menu_message(str_target, FBCON_TITLE_MSG, common_factor);
display_fbcon_menu_message("\n< More options\n",
FBCON_COMMON_MSG, common_factor);
display_fbcon_menu_message("press VOLUME keys\n\n",
FBCON_SUBTITLE_MSG, common_factor);
if(boot_verify_info[type].warning_msg != NULL)
display_fbcon_menu_message((char*)boot_verify_info[type].warning_msg,
FBCON_COMMON_MSG, common_factor);
display_fbcon_menu_message("g.co/placeholder\n",
boot_verify_info[type].msg_type, common_factor);
if (type == DISPLAY_MENU_YELLOW) {
fp_buf = get_boot_fingerprint(&fp_size);
if (fp_buf != NULL) {
strncpy(fp_str_temp, (char const *)fp_buf, fp_size);
for (i = 0; i < fp_size; i++) {
if(i == fp_size - 1)
sprintf(str_temp, "%02x", fp_str_temp[i]);
else
sprintf(str_temp, "%02x-", fp_str_temp[i]);
strcat(fp_str, str_temp);
}
}
display_fbcon_menu_message("ID:", FBCON_COMMON_MSG, common_factor);
display_fbcon_menu_message(fp_str, FBCON_COMMON_MSG, common_factor);
}
display_fbcon_menu_message("\n\nIf no key pressed:\n"\
"Your device will boot in 5 seconds\n\n", FBCON_COMMON_MSG, common_factor);
msg_info->msg_type = type;
if(str_target) {
free(str_target);
}
}
#endif
void display_boot_verified_option(struct select_msg_info *msg_info)
{
int i = 0;
int len = 0;
fbcon_clear();
memset(msg_info, 0, sizeof(struct select_msg_info));
len = ARRAY_SIZE(verify_option_menu);
display_fbcon_menu_message("Options menu:\n\n",
FBCON_COMMON_MSG, big_factor);
display_fbcon_menu_message("Press volume key to select, and "\
"press power key to select\n\n", FBCON_COMMON_MSG, common_factor);
for (i = 0; i < len; i++) {
fbcon_draw_line(FBCON_COMMON_MSG);
msg_info->option_start[i] = fbcon_get_current_line();
display_fbcon_menu_message(verify_option_menu[i],
FBCON_COMMON_MSG, common_factor);
msg_info->option_bg[i]= fbcon_get_current_bg();
msg_info->option_end[i]= fbcon_get_current_line();
}
fbcon_draw_line(FBCON_COMMON_MSG);
msg_info->msg_type = DISPLAY_MENU_MORE_OPTION;
msg_info->option_num = len;
}
void display_fastboot_menu(struct select_msg_info *fastboot_msg_info,
int option_index)
{
int len;
int msg_type = FBCON_COMMON_MSG;
char msg_buf[64];
char msg[128];
fbcon_clear();
memset(fastboot_msg_info, 0, sizeof(struct select_msg_info));
len = ARRAY_SIZE(fastboot_option_menu);
switch(option_index) {
case 0:
msg_type = FBCON_GREEN_MSG;
break;
case 1:
case 2:
msg_type = FBCON_RED_MSG;
break;
case 3:
msg_type = FBCON_COMMON_MSG;
break;
}
fbcon_draw_line(msg_type);
display_fbcon_menu_message(fastboot_option_menu[option_index],
msg_type, big_factor);
fbcon_draw_line(msg_type);
display_fbcon_menu_message("\n\nPress volume key to select, and "\
"press power key to select\n\n", FBCON_COMMON_MSG, common_factor);
display_fbcon_menu_message("FASTBOOT MODE\n", FBCON_RED_MSG, common_factor);
get_product_name((unsigned char *) msg_buf);
snprintf(msg, sizeof(msg), "PRODUCT_NAME - %s\n", msg_buf);
display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
memset(msg_buf, 0, sizeof(msg_buf));
smem_get_hw_platform_name((unsigned char *) msg_buf, sizeof(msg_buf));
snprintf(msg, sizeof(msg), "VARIANT - %s %s\n",
msg_buf, target_is_emmc_boot()? "eMMC":"UFS");
display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
memset(msg_buf, 0, sizeof(msg_buf));
get_bootloader_version((unsigned char *) msg_buf);
snprintf(msg, sizeof(msg), "BOOTLOADER VERSION - %s\n",
msg_buf);
display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
memset(msg_buf, 0, sizeof(msg_buf));
get_baseband_version((unsigned char *) msg_buf);
snprintf(msg, sizeof(msg), "BASEBAND VERSION - %s\n",
msg_buf);
display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
memset(msg_buf, 0, sizeof(msg_buf));
target_serialno((unsigned char *) msg_buf);
snprintf(msg, sizeof(msg), "SERIAL NUMBER - %s\n", msg_buf);
display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
snprintf(msg, sizeof(msg), "SECURE BOOT - %s\n",
is_secure_boot_enable()? "enabled":"disabled");
display_fbcon_menu_message(msg, FBCON_COMMON_MSG, common_factor);
snprintf(msg, sizeof(msg), "DEVICE STATE - %s\n",
is_device_locked()? "locked":"unlocked");
display_fbcon_menu_message(msg, FBCON_RED_MSG, common_factor);
fastboot_msg_info->msg_type = DISPLAY_MENU_FASTBOOT;
fastboot_msg_info->option_num = len;
}
static void display_menu_thread_start(struct select_msg_info *msg_info)
{
thread_t *thr;
if (!is_thread_start) {
thr = thread_create("selectkeydetect", &select_msg_keys_detect,
(void*)msg_info, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
if (!thr) {
dprintf(CRITICAL, "ERROR: creat device status detect thread failed!!\n");
return;
}
thread_resume(thr);
}
is_thread_start = true;
}
void display_unlock_menu_thread(int type)
{
struct select_msg_info *unlock_menu_msg_info;
unlock_menu_msg_info = &msg_info;
set_message_factor();
display_unlock_menu(unlock_menu_msg_info, type);
dprintf(INFO, "creating unlock keys detect thread\n");
display_menu_thread_start(unlock_menu_msg_info);
}
void display_fastboot_menu_thread()
{
struct select_msg_info *fastboot_menu_msg_info;
fastboot_menu_msg_info = &msg_info;
set_message_factor();
display_fastboot_menu(fastboot_menu_msg_info, 0);
dprintf(INFO, "creating fastboot menu keys detect thread\n");
display_menu_thread_start(fastboot_menu_msg_info);
}
#if VERIFIED_BOOT
void display_bootverify_menu_thread(int type)
{
struct select_msg_info *bootverify_menu_msg_info;
bootverify_menu_msg_info = &msg_info;
set_message_factor();
display_boot_verified_menu(bootverify_menu_msg_info, type);
dprintf(INFO, "creating boot verify keys detect thread\n");
display_menu_thread_start(bootverify_menu_msg_info);
}
#endif