1578 lines
42 KiB
C
1578 lines
42 KiB
C
/*
|
|
* Copyright (c) 2009, Google Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
|
|
*
|
|
* Copyright (c) 2011, Rick@xda-developers.com, 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 Code Aurora 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 <arch/arm.h>
|
|
#include <arch/ops.h>
|
|
#include <kernel/thread.h>
|
|
#include <platform/iomap.h>
|
|
#include <platform/timer.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <app.h>
|
|
#include <bits.h>
|
|
#include <compiler.h>
|
|
#include <debug.h>
|
|
#include <err.h>
|
|
#include <hsusb.h>
|
|
#include <platform.h>
|
|
#include <reg.h>
|
|
#include <smem.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
|
|
#include <dev/flash.h>
|
|
#include <dev/fbcon.h>
|
|
#include <dev/keys.h>
|
|
#include <dev/udc.h>
|
|
|
|
#include <lib/ptable.h>
|
|
#include <lib/vptable.h>
|
|
|
|
#include "bootimg.h"
|
|
#include "fastboot.h"
|
|
#include "recovery.h"
|
|
#include "version.h"
|
|
|
|
#define EXPAND(NAME) #NAME
|
|
#define TARGET(NAME) EXPAND(NAME)
|
|
#define DEFAULT_CMDLINE "";
|
|
|
|
#ifdef MEMBASE
|
|
#define EMMC_BOOT_IMG_HEADER_ADDR (0xFF000+(MEMBASE))
|
|
#else
|
|
#define EMMC_BOOT_IMG_HEADER_ADDR 0xFF000
|
|
#endif
|
|
|
|
#define RECOVERY_MODE 0x77665502
|
|
#define FASTBOOT_MODE 0x77665500
|
|
|
|
#ifndef __PLATFORM_SPLASH_H
|
|
#define __PLATFORM_SPLASH_H
|
|
#endif
|
|
|
|
#define SPLASH_IMAGE_WIDTH 153
|
|
#define SPLASH_IMAGE_HEIGHT 480
|
|
|
|
#define FONT_WIDTH 5
|
|
#define FONT_HEIGHT 12
|
|
|
|
#define SCREEN_WIDTH 480
|
|
#define SCREEN_HEIGHT 800
|
|
|
|
#define ERR_KEY_CHANGED 99
|
|
|
|
void platform_uninit_timer(void);
|
|
void *target_get_scratch_address(void);
|
|
void reboot_device(unsigned reboot_reason);
|
|
void target_battery_charging_enable(unsigned enable, unsigned disconnect);
|
|
void display_shutdown(void);
|
|
void nand_erase(const char *arg);
|
|
void cmd_powerdown(const char *arg, void *data, unsigned sz);
|
|
void disp_menu(int selection, char *menu[], int loop);
|
|
void shutdown(void);
|
|
void keypad_init(void);
|
|
void display_init(void);
|
|
void htcleo_ptable_dump(struct ptable *ptable);
|
|
void cmd_dmesg(const char *arg, void *data, unsigned sz);
|
|
void target_display_init();
|
|
void cmd_oem_register();
|
|
void shutdown_device(void);
|
|
void dispmid(const char *fmt, int sel);
|
|
void start_keylistener(void);
|
|
void eval_keyup(void);
|
|
void eval_keydown(void);
|
|
void draw_clk_header(void);
|
|
void cmd_flashlight(void);
|
|
void redraw_menu(void);
|
|
void prnt_nand_stat(void);
|
|
|
|
int target_is_emmc_boot(void);
|
|
int boot_linux_from_flash(void);
|
|
|
|
int key_listener(void *arg);
|
|
|
|
unsigned boot_into_sboot = 0;
|
|
unsigned board_machtype(void);
|
|
unsigned get_boot_reason(void);
|
|
unsigned check_reboot_mode(void);
|
|
unsigned* target_atag_mem(unsigned* ptr);
|
|
|
|
unsigned long long mmc_ptn_size (unsigned char * name);
|
|
unsigned long long mmc_ptn_offset (unsigned char * name);
|
|
|
|
unsigned int mmc_read (unsigned long long data_addr, unsigned int* out, unsigned int data_len);
|
|
unsigned int mmc_write (unsigned long long data_addr, unsigned int data_len, unsigned int* in);
|
|
|
|
uint16_t keys[] = {KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_SOFT1, KEY_SEND, KEY_CLEAR, KEY_BACK, KEY_HOME};
|
|
uint16_t keyp = ERR_KEY_CHANGED;
|
|
|
|
static const char *emmc_cmdline = " androidboot.emmc=true";
|
|
static const char *battchg_pause = " androidboot.mode=offmode_charging";
|
|
|
|
char amss_ver[16];
|
|
char *Menuid = "HBOOT";
|
|
|
|
struct atag_ptbl_entry
|
|
{
|
|
char name[16];
|
|
unsigned offset;
|
|
unsigned size;
|
|
unsigned flags;
|
|
};
|
|
struct menu_item {
|
|
char mTitle[64];
|
|
char command[64];
|
|
|
|
int x;
|
|
int y;
|
|
};
|
|
|
|
#define MAX_MENU 16
|
|
|
|
struct menu {
|
|
int maxarl;
|
|
int selectedi;
|
|
|
|
int top_offset;
|
|
int bottom_offset;
|
|
|
|
struct menu_item item[MAX_MENU];
|
|
};
|
|
struct menu main_menu;
|
|
struct menu sett_menu;
|
|
struct menu *active_menu;
|
|
|
|
static struct udc_device surf_udc_device = {
|
|
.vendor_id = 0x18d1,
|
|
.product_id = 0x0D02,
|
|
.version_id = 0x0001,
|
|
.manufacturer = "Google",
|
|
.product = "Android",
|
|
};
|
|
void update_radio_ver(void)
|
|
{
|
|
unsigned ver_base = 0xef230;
|
|
// Dump AMMS version
|
|
*(unsigned int *) (*amss_ver + 0x0) = readl(MSM_SHARED_BASE + ver_base + 0x0);
|
|
*(unsigned int *) (*amss_ver + 0x4) = readl(MSM_SHARED_BASE + ver_base + 0x4);
|
|
*(unsigned int *) (*amss_ver + 0x8) = readl(MSM_SHARED_BASE + ver_base + 0x8);
|
|
*(unsigned int *) (*amss_ver + 0xc) = readl(MSM_SHARED_BASE + ver_base + 0xc);
|
|
amss_ver[15] = 0;
|
|
return;
|
|
}
|
|
void parse_tag_msm_wifi_from_spl(void)
|
|
{
|
|
#define MSM_SPLHOOD_BASE 0xF9200000 //IOMEM(0xF9200000)
|
|
#define MSM_SPLHOOD_PHYS 0x0
|
|
#define MSM_SPLHOOD_SIZE SZ_1M
|
|
uint32_t id1, id2, id3, id4, id5, id6;
|
|
//uint32_t id_base = 0xFC028; //real mac offset found in spl for haret.exe on WM
|
|
uint32_t id_base = 0xef2a0;
|
|
id1 = readl(MSM_SHARED_BASE + id_base + 0x0);
|
|
id2 = readl(MSM_SHARED_BASE + id_base + 0x1);
|
|
id3 = readl(MSM_SHARED_BASE + id_base + 0x2);
|
|
id4 = readl(MSM_SHARED_BASE + id_base + 0x3);
|
|
id5 = readl(MSM_SHARED_BASE + id_base + 0x4);
|
|
id6 = readl(MSM_SHARED_BASE + id_base + 0x5);
|
|
char nvs_mac_addr[32];
|
|
sprintf(nvs_mac_addr, "macaddr=%i:%i:%i:%i:%i:%i\n", id1 , id2 , id3 , id4 , id5 , id6 );
|
|
printf("\n\nDevice Real Wifi Mac Address: %s\n", nvs_mac_addr);
|
|
return;
|
|
}
|
|
unsigned get_radiover(void){
|
|
unsigned radio_ver = readl(MSM_SHARED_BASE+0xef220);
|
|
return radio_ver;
|
|
}
|
|
unsigned get_imei(void){
|
|
unsigned dev_imei = readl(MSM_SHARED_BASE+0xef260);
|
|
return dev_imei;
|
|
}
|
|
unsigned get_pid(void){
|
|
unsigned dev_pid = readl(MSM_SHARED_BASE+0xef210);
|
|
return dev_pid;
|
|
}
|
|
void selector_disable(void)
|
|
{
|
|
fbcon_set_x_cord(active_menu->item[active_menu->selectedi].x);
|
|
fbcon_set_y_cord(active_menu->item[active_menu->selectedi].y);
|
|
fbcon_forcetg(true);
|
|
fbcon_reset_colors_rgb555();
|
|
_dputs(active_menu->item[active_menu->selectedi].mTitle);
|
|
fbcon_forcetg(false);
|
|
}
|
|
void selector_enable(void)
|
|
{
|
|
fbcon_set_x_cord(active_menu->item[active_menu->selectedi].x);
|
|
fbcon_set_y_cord(active_menu->item[active_menu->selectedi].y);
|
|
fbcon_settg(0x001f);
|
|
fbcon_setfg(0xffff);
|
|
_dputs(active_menu->item[active_menu->selectedi].mTitle);
|
|
fbcon_reset_colors_rgb555();
|
|
}
|
|
void eval_command(void)
|
|
{
|
|
char command[32];
|
|
strcpy(command, active_menu->item[active_menu->selectedi].command);
|
|
|
|
if (!memcmp(command,"boot_recv", strlen(command))){
|
|
fbcon_resetdisp();
|
|
boot_into_sboot = 0;
|
|
boot_into_recovery = 1;
|
|
boot_linux_from_flash();
|
|
return;
|
|
|
|
} else if (!memcmp(command,"prnt_clrs", strlen(command))){
|
|
fbcon_resetdisp();
|
|
draw_clk_header();
|
|
redraw_menu();
|
|
selector_enable();
|
|
return;
|
|
|
|
} else if (!memcmp(command,"boot_sbot", strlen(command))){
|
|
fbcon_resetdisp();
|
|
boot_into_sboot = 1;
|
|
boot_into_recovery = 0;
|
|
boot_linux_from_flash();
|
|
return;
|
|
|
|
} else if (!memcmp(command,"boot_nand", strlen(command))){
|
|
fbcon_resetdisp();
|
|
boot_into_sboot = 0;
|
|
boot_into_recovery = 0;
|
|
boot_linux_from_flash();
|
|
return;
|
|
|
|
}else if (!memcmp(command,"prnt_stat", strlen(command))){
|
|
/*fbcon_resetdisp();
|
|
draw_clk_header();
|
|
redraw_menu();*/
|
|
vpart_list();
|
|
return;
|
|
}else if (!memcmp(command,"prnt_nand", strlen(command))){
|
|
prnt_nand_stat();
|
|
return;
|
|
}else if (!memcmp(command,"goto_rept", strlen(command))){
|
|
printf("\n ERROR!: Feature not compiled");
|
|
return;
|
|
}else if (!memcmp(command,"goto_sett", strlen(command))){
|
|
//sett_menu.top_offset = main_menu.top_offset;
|
|
//sett_menu.bottom_offset = main_menu.bottom_offset;
|
|
fbcon_resetdisp();
|
|
Menuid="Settings";
|
|
draw_clk_header();
|
|
active_menu = &sett_menu;
|
|
redraw_menu();
|
|
selector_enable();
|
|
return;
|
|
|
|
}else if (!memcmp(command,"goto_main", strlen(command))){
|
|
//vpart_list();
|
|
fbcon_resetdisp();
|
|
Menuid="HBOOT";
|
|
draw_clk_header();
|
|
active_menu = &main_menu;
|
|
redraw_menu();
|
|
selector_enable();
|
|
return;
|
|
|
|
}else if (!memcmp(command,"acpu_ggwp", strlen(command))){
|
|
reboot_device(0);
|
|
return;
|
|
}else if (!memcmp(command,"acpu_bgwp", strlen(command))){
|
|
reboot_device(FASTBOOT_MODE);
|
|
return;
|
|
}else if (!memcmp(command,"acpu_pawn", strlen(command))){
|
|
shutdown();
|
|
return;
|
|
}else if (!memcmp(command,"enable_extrom", strlen(command))){
|
|
vpart_enable_extrom();
|
|
printf("Will Auto-Reboot in 2 Seconds for changes to take place.");
|
|
thread_sleep(2000);
|
|
reboot_device(FASTBOOT_MODE);
|
|
return;
|
|
}else if (!memcmp(command,"disable_extrom", strlen(command))){
|
|
vpart_disable_extrom();
|
|
printf("Will Auto-Reboot in 2 Seconds for changes to take place.");
|
|
thread_sleep(2000);
|
|
reboot_device(FASTBOOT_MODE);
|
|
return;
|
|
}else if (!memcmp(command,"init_flsh", strlen(command))){
|
|
cmd_flashlight();
|
|
return;
|
|
}else if (!memcmp(command,"MSM_wifimac",strlen(command))){
|
|
parse_tag_msm_wifi_from_spl();
|
|
return;
|
|
}
|
|
printf("HBOOT BUG: Somehow fell through eval_cmd()\n");
|
|
return;
|
|
}
|
|
void redraw_menu(void)
|
|
{
|
|
if (didyouscroll())
|
|
{
|
|
fbcon_resetdisp();
|
|
draw_clk_header();
|
|
}
|
|
int current_offset = fbcon_get_y_cord();
|
|
|
|
if (active_menu->top_offset < 1){
|
|
active_menu->top_offset = current_offset;
|
|
}else{
|
|
fbcon_set_y_cord(active_menu->top_offset);
|
|
}
|
|
if (active_menu->top_offset > 1 && active_menu->bottom_offset > 1)
|
|
fbcon_clear_region(active_menu->top_offset,active_menu->bottom_offset);
|
|
|
|
for (uint8_t i=0;; i++){
|
|
if ((strlen(active_menu->item[i].mTitle) != 0) && !(i > active_menu->maxarl) ){
|
|
_dputs(" ");
|
|
if(active_menu->item[i].x == 0)
|
|
active_menu->item[i].x = fbcon_get_x_cord();
|
|
if(active_menu->item[i].y == 0)
|
|
active_menu->item[i].y = fbcon_get_y_cord();
|
|
_dputs(active_menu->item[i].mTitle);
|
|
_dputs("\n");
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
_dputs("\n");
|
|
|
|
if (active_menu->bottom_offset < 1){
|
|
active_menu->bottom_offset = fbcon_get_y_cord();
|
|
}else{
|
|
fbcon_set_y_cord(active_menu->bottom_offset);
|
|
}
|
|
|
|
if (current_offset > fbcon_get_y_cord())
|
|
fbcon_set_y_cord(current_offset);
|
|
|
|
}
|
|
static int menu_item_down()
|
|
{
|
|
thread_set_priority(HIGHEST_PRIORITY);
|
|
|
|
if (didyouscroll())
|
|
{
|
|
redraw_menu();
|
|
}
|
|
|
|
int current_y_offset = fbcon_get_y_cord();
|
|
int current_x_offset = fbcon_get_x_cord();
|
|
|
|
selector_disable();
|
|
|
|
if (active_menu->selectedi == (active_menu->maxarl-1))
|
|
{
|
|
active_menu->selectedi=0;
|
|
} else {
|
|
active_menu->selectedi++;
|
|
}
|
|
|
|
selector_enable();
|
|
|
|
fbcon_set_y_cord(current_y_offset);
|
|
fbcon_set_x_cord(current_x_offset);
|
|
|
|
thread_set_priority(DEFAULT_PRIORITY);
|
|
return 0;
|
|
}
|
|
static int menu_item_up()
|
|
{
|
|
thread_set_priority(HIGHEST_PRIORITY);
|
|
|
|
if (didyouscroll())
|
|
{
|
|
redraw_menu();
|
|
}
|
|
|
|
int current_y_offset = fbcon_get_y_cord();
|
|
int current_x_offset = fbcon_get_x_cord();
|
|
|
|
selector_disable();
|
|
|
|
if ((active_menu->selectedi) == 0)
|
|
{
|
|
active_menu->selectedi=(active_menu->maxarl-1);
|
|
} else {
|
|
active_menu->selectedi--;
|
|
}
|
|
|
|
selector_enable();
|
|
|
|
fbcon_set_y_cord(current_y_offset);
|
|
fbcon_set_x_cord(current_x_offset);
|
|
|
|
thread_set_priority(DEFAULT_PRIORITY);
|
|
return 0;
|
|
}
|
|
void add_menu_item(struct menu *xmenu,const char *name,const char *command){
|
|
if(xmenu->maxarl==MAX_MENU){
|
|
printf("Menu: is overloaded with entry %s",name);
|
|
return;
|
|
}
|
|
strcpy(xmenu->item[xmenu->maxarl].mTitle,name);
|
|
strcpy(xmenu->item[xmenu->maxarl].command,command);
|
|
|
|
xmenu->item[xmenu->maxarl].x = 0;
|
|
xmenu->item[xmenu->maxarl].y = 0;
|
|
|
|
xmenu->maxarl++;
|
|
return;
|
|
}
|
|
void init_menu(){
|
|
draw_clk_header();
|
|
|
|
main_menu.top_offset = 0;
|
|
main_menu.bottom_offset = 0;
|
|
main_menu.selectedi = 0;
|
|
main_menu.maxarl = 0;
|
|
|
|
add_menu_item(&main_menu, "ANDROID NAND" , "boot_nand");
|
|
add_menu_item(&main_menu, "ANDROID EMMC" , "boot_sbot");
|
|
add_menu_item(&main_menu, "RECOVERY" , "boot_recv");
|
|
add_menu_item(&main_menu, "FLASHLIGHT" , "init_flsh");
|
|
add_menu_item(&main_menu, "SETTINGS" , "goto_sett");
|
|
add_menu_item(&main_menu, "REBOOT" , "acpu_ggwp");
|
|
add_menu_item(&main_menu, "REBOOT HBOOT" , "acpu_bgwp");
|
|
add_menu_item(&main_menu, "POWERDOWN" , "acpu_pawn");
|
|
|
|
sett_menu.top_offset = 0;
|
|
sett_menu.bottom_offset = 0;
|
|
sett_menu.selectedi = 0;
|
|
sett_menu.maxarl = 0;
|
|
|
|
if (vparts.extrom_enabled)
|
|
{
|
|
add_menu_item(&sett_menu,"ExtROM ENABLED, SELECT TO DISABLE !","disable_extrom");
|
|
}else{
|
|
add_menu_item(&sett_menu,"ExtROM DISABLED, SELECT TO ENABLE !","enable_extrom");
|
|
}
|
|
|
|
add_menu_item(&sett_menu, "PARSE_TAG_MSM_WIFI_FROM_SPL", "MSM_wifimac");
|
|
add_menu_item(&sett_menu, "PRINT NAND STATS" , "prnt_nand");
|
|
add_menu_item(&sett_menu, "PRINT PART STATS ", "prnt_stat");
|
|
add_menu_item(&sett_menu, "REPARTITION NAND\n", "goto_rept");
|
|
add_menu_item(&sett_menu, "BACK" , "goto_main");
|
|
|
|
active_menu = &main_menu;
|
|
redraw_menu();
|
|
selector_enable();
|
|
start_keylistener();
|
|
}
|
|
void eval_keydown(void){
|
|
if (keyp == ERR_KEY_CHANGED) {return;}
|
|
switch (keys[keyp]){
|
|
case KEY_VOLUMEUP:
|
|
//thread_resume(thread_create("sel_up", &menu_item_up, NULL, HIGHEST_PRIORITY, DEFAULT_STACK_SIZE));
|
|
menu_item_up();
|
|
break;
|
|
case KEY_VOLUMEDOWN:
|
|
//thread_resume(thread_create("sel_dn", &menu_item_down, NULL, HIGHEST_PRIORITY, DEFAULT_STACK_SIZE));
|
|
menu_item_down();
|
|
break;
|
|
case KEY_SEND: // dial
|
|
eval_command();
|
|
break;
|
|
case KEY_CLEAR: // hangup
|
|
break;
|
|
case KEY_BACK:
|
|
break;
|
|
}
|
|
}
|
|
void eval_keyup(void){
|
|
if (keyp == ERR_KEY_CHANGED) {return;}
|
|
switch (keys[keyp]){
|
|
case KEY_VOLUMEUP:
|
|
break;
|
|
case KEY_VOLUMEDOWN:
|
|
break;
|
|
case KEY_SEND: // dial
|
|
break;
|
|
case KEY_CLEAR: //hangup
|
|
break;
|
|
case KEY_BACK:
|
|
break;
|
|
}
|
|
}
|
|
int key_repeater(void *arg)
|
|
{
|
|
uint16_t last_key_i_remember = keyp;
|
|
uint8_t counter1 = 0;
|
|
for(;;)
|
|
{
|
|
if ((keyp == ERR_KEY_CHANGED || (last_key_i_remember!=keyp)))
|
|
{
|
|
thread_exit(0);
|
|
return 0;
|
|
} else {
|
|
thread_sleep(10);
|
|
counter1++;
|
|
if(counter1>75)
|
|
{
|
|
counter1=0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while((keyp!=ERR_KEY_CHANGED)&&(last_key_i_remember==keyp)&&(keys_get_state(keys[keyp])!=0))
|
|
{
|
|
eval_keydown();
|
|
thread_sleep(100);
|
|
}
|
|
thread_exit(0);
|
|
return 0;
|
|
}
|
|
int key_listener(void *arg)
|
|
{
|
|
for (;;) {
|
|
for(uint16_t i=0; i< sizeof(keys)/sizeof(uint16_t); i++)
|
|
if (keys_get_state(keys[i]) != 0){
|
|
keyp = i;
|
|
eval_keydown();
|
|
thread_resume(thread_create("key_repeater", &key_repeater, NULL, DEFAULT_PRIORITY, 4096));
|
|
while (keys_get_state(keys[keyp]) !=0){thread_sleep(1);}
|
|
eval_keyup();
|
|
keyp = 99;
|
|
}
|
|
}
|
|
thread_exit(0);
|
|
return 0;
|
|
}
|
|
void start_keylistener(void){
|
|
thread_resume(thread_create("key_listener", &key_listener, 0, LOW_PRIORITY, 4096));
|
|
}
|
|
void draw_clk_header(void){
|
|
fbcon_setfg(0x02E0);
|
|
printf("\n LEO100 HX-BC SHIP S-OFF\n HBOOT-0.01.0000\n TOUCH PANEL-MicroP(LED) 0x05\n SPL-CotullaHSPL 0x30\n RADIO-%s\n %s\n\n\n ", amss_ver, BUILD_DATE);
|
|
fbcon_settg(0x001f);fbcon_setfg(0xffff);
|
|
_dputs(Menuid);
|
|
fbcon_settg(0xffff);fbcon_setfg(0xC3A0);
|
|
_dputs("\n\n\n <VOL UP> to previous item\n <VOL DOWN> to next item\n <CALL> to select item\n <BACK> to return\n\n\n");
|
|
fbcon_setfg(0x0000);
|
|
}
|
|
void cmd_powerdown(const char *arg, void *data, unsigned sz)
|
|
{
|
|
dprintf(INFO, "Powering down the device\n");
|
|
fastboot_okay("Device Powering Down");
|
|
shutdown();
|
|
thread_exit(0);
|
|
}
|
|
static void ptentry_to_tag(unsigned **ptr, struct ptentry *ptn)
|
|
{
|
|
struct atag_ptbl_entry atag_ptn;
|
|
|
|
if (ptn->type == TYPE_MODEM_PARTITION)
|
|
return;
|
|
memcpy(atag_ptn.name, ptn->name, 16);
|
|
atag_ptn.name[15] = '\0';
|
|
atag_ptn.offset = ptn->start;
|
|
atag_ptn.size = ptn->length;
|
|
atag_ptn.flags = ptn->flags;
|
|
memcpy(*ptr, &atag_ptn, sizeof(struct atag_ptbl_entry));
|
|
*ptr += sizeof(struct atag_ptbl_entry) / sizeof(unsigned);
|
|
}
|
|
|
|
unsigned target_pause_for_battery_charge(void);
|
|
void htcleo_boot(void* kernel,unsigned machtype,void* tags);
|
|
|
|
void boot_linux(void *kernel, unsigned *tags,
|
|
const char *cmdline, unsigned machtype,
|
|
void *ramdisk, unsigned ramdisk_size)
|
|
{
|
|
unsigned *ptr = tags;
|
|
unsigned pcount = 0;
|
|
/* Unused variable :o */
|
|
//void (*entry)(unsigned,unsigned,unsigned*) = kernel;
|
|
struct ptable *ptable;
|
|
int cmdline_len = 0;
|
|
int have_cmdline = 0;
|
|
int pause_at_bootup = 0;
|
|
|
|
/* CORE */
|
|
*ptr++ = 2;
|
|
*ptr++ = 0x54410001;
|
|
|
|
if (ramdisk_size) {
|
|
*ptr++ = 4;
|
|
*ptr++ = 0x54420005;
|
|
*ptr++ = (unsigned)ramdisk;
|
|
*ptr++ = ramdisk_size;
|
|
}
|
|
|
|
ptr = target_atag_mem(ptr);
|
|
|
|
if (!target_is_emmc_boot()) {
|
|
/* Skip NAND partition ATAGS for eMMC boot */
|
|
if ((ptable = flash_get_ptable()) && (ptable->count != 0)) {
|
|
int i;
|
|
for(i=0; i < ptable->count; i++) {
|
|
struct ptentry *ptn;
|
|
ptn = ptable_get(ptable, i);
|
|
if (ptn->type == TYPE_APPS_PARTITION)
|
|
pcount++;
|
|
}
|
|
*ptr++ = 2 + (pcount * (sizeof(struct atag_ptbl_entry) /
|
|
sizeof(unsigned)));
|
|
*ptr++ = 0x4d534d70;
|
|
for (i = 0; i < ptable->count; ++i)
|
|
ptentry_to_tag(&ptr, ptable_get(ptable, i));
|
|
}
|
|
}
|
|
|
|
if (cmdline && cmdline[0]) {
|
|
cmdline_len = strlen(cmdline);
|
|
have_cmdline = 1;
|
|
}
|
|
if (target_is_emmc_boot()) {
|
|
cmdline_len += strlen(emmc_cmdline);
|
|
}
|
|
if (target_pause_for_battery_charge()) {
|
|
pause_at_bootup = 1;
|
|
cmdline_len += strlen(battchg_pause);
|
|
}
|
|
if (cmdline_len > 0) {
|
|
const char *src;
|
|
char *dst;
|
|
unsigned n;
|
|
/* include terminating 0 and round up to a word multiple */
|
|
n = (cmdline_len + 4) & (~3);
|
|
*ptr++ = (n / 4) + 2;
|
|
*ptr++ = 0x54410009;
|
|
dst = (char *)ptr;
|
|
if (have_cmdline) {
|
|
src = cmdline;
|
|
while ((*dst++ = *src++));
|
|
}
|
|
if (target_is_emmc_boot()) {
|
|
src = emmc_cmdline;
|
|
if (have_cmdline) --dst;
|
|
have_cmdline = 1;
|
|
while ((*dst++ = *src++));
|
|
}
|
|
if (pause_at_bootup) {
|
|
src = battchg_pause;
|
|
if (have_cmdline) --dst;
|
|
while ((*dst++ = *src++));
|
|
}
|
|
ptr += (n / 4);
|
|
}
|
|
|
|
/* END */
|
|
*ptr++ = 0;
|
|
*ptr++ = 0;
|
|
|
|
dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)\n",
|
|
kernel, ramdisk, ramdisk_size);
|
|
if (cmdline)
|
|
dprintf(INFO, "cmdline: %s\n", cmdline);
|
|
|
|
enter_critical_section();
|
|
platform_uninit_timer();
|
|
arch_disable_cache(UCACHE);
|
|
arch_disable_mmu();
|
|
#if DISPLAY_SPLASH_SCREEN
|
|
display_shutdown();
|
|
#endif
|
|
|
|
htcleo_boot(kernel, machtype, tags);
|
|
//entry(0, machtype, tags);
|
|
}
|
|
|
|
unsigned page_size = 0;
|
|
unsigned page_mask = 0;
|
|
|
|
#define ROUND_TO_PAGE(x,y) (((x) + (y)) & (~(y)))
|
|
|
|
static unsigned char buf[4096]; //Equal to max-supported pagesize
|
|
/*
|
|
int boot_linux_from_mmc(void)
|
|
{
|
|
struct boot_img_hdr *hdr = (void*) buf;
|
|
struct boot_img_hdr *uhdr;
|
|
unsigned offset = 0;
|
|
unsigned long long ptn = 0;
|
|
unsigned n = 0;
|
|
const char *cmdline;
|
|
|
|
uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
|
|
if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE))
|
|
{
|
|
dprintf(INFO, "Unified boot method!\n");
|
|
hdr = uhdr;
|
|
goto unified_boot;
|
|
}
|
|
if(!boot_into_recovery)
|
|
{
|
|
ptn = mmc_ptn_offset("boot");
|
|
if(ptn == 0) {
|
|
dprintf(CRITICAL, "ERROR: No boot partition found\n");
|
|
return -1;
|
|
}
|
|
} else {
|
|
ptn = mmc_ptn_offset("recovery");
|
|
if(ptn == 0) {
|
|
dprintf(CRITICAL, "ERROR: No recovery partition found\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (mmc_read(ptn + offset, (unsigned int *)buf, page_size)) {
|
|
dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
|
|
return -1;
|
|
}
|
|
|
|
if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
|
|
dprintf(CRITICAL, "ERROR: Invaled boot image header\n");
|
|
return -1;
|
|
}
|
|
|
|
if (hdr->page_size && (hdr->page_size != page_size)) {
|
|
page_size = hdr->page_size;
|
|
page_mask = page_size - 1;
|
|
}
|
|
offset += page_size;
|
|
|
|
n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
|
|
if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, n)) {
|
|
dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
|
|
return -1;
|
|
}
|
|
offset += n;
|
|
|
|
n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
|
|
if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, n)) {
|
|
dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
|
|
return -1;
|
|
}
|
|
offset += n;
|
|
|
|
unified_boot:
|
|
dprintf(INFO, "\nkernel @ %x (%d bytes)\n", hdr->kernel_addr, hdr->kernel_size);
|
|
dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr, hdr->ramdisk_size);
|
|
if(hdr->cmdline[0]) {
|
|
cmdline = (char*) hdr->cmdline;
|
|
} else {
|
|
cmdline = DEFAULT_CMDLINE;
|
|
}
|
|
strcat(cmdline," clk=");
|
|
strcat(cmdline,cLK_version);
|
|
|
|
dprintf(INFO, "cmdline = '%s'\n", cmdline);
|
|
|
|
dprintf(INFO, "\nBooting Linux\n");
|
|
|
|
boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR,
|
|
(const char *)cmdline, board_machtype(),
|
|
(void *)hdr->ramdisk_addr, hdr->ramdisk_size);
|
|
|
|
return 0;
|
|
}
|
|
|
|
*/
|
|
int boot_linux_from_flash(void)
|
|
{
|
|
struct boot_img_hdr *hdr = (void*) buf;
|
|
unsigned n;
|
|
struct ptentry *ptn;
|
|
struct ptable *ptable;
|
|
unsigned offset = 0;
|
|
char *cmdline;
|
|
/*
|
|
if (target_is_emmc_boot()) {
|
|
hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
|
|
if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
|
|
dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
|
|
return -1;
|
|
}
|
|
goto continue_boot;
|
|
}
|
|
*/
|
|
ptable = flash_get_ptable();
|
|
if (ptable == NULL) {
|
|
dprintf(CRITICAL, "ERROR: Partition table not found\n");
|
|
return -1;
|
|
}
|
|
/* Fixed Hang after failed boot */
|
|
if (boot_into_recovery){ // Boot from recovery
|
|
boot_into_sboot = 0;
|
|
dprintf(ALWAYS,"\n\nBooting to recovery...\n\n");
|
|
|
|
ptn = ptable_find(ptable, "recovery");
|
|
if (ptn == NULL) {
|
|
dprintf(CRITICAL, "ERROR: No recovery partition found\n");
|
|
boot_into_recovery=0;
|
|
return -1;
|
|
}
|
|
|
|
} else if (boot_into_sboot){ //Boot from sboot partition
|
|
dprintf(INFO,"\n\nBooting from sboot partition...\n\n");
|
|
ptn = ptable_find(ptable,"sboot");
|
|
if (ptn == NULL){
|
|
dprintf(CRITICAL,"ERROR: No sboot partition found!\n");
|
|
boot_into_sboot=0;
|
|
return -1;
|
|
}
|
|
|
|
} else { // Standard boot
|
|
|
|
dprintf(INFO,"\n\nNormal boot...\n\n");
|
|
ptn = ptable_find(ptable, "boot");
|
|
if (ptn == NULL) {
|
|
dprintf(CRITICAL, "ERROR: No boot partition found\n");
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
if (flash_read(ptn, offset, buf, page_size)) {
|
|
dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");
|
|
return -1;
|
|
}
|
|
offset += page_size;
|
|
|
|
if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
|
|
dprintf(CRITICAL, "ERROR: Invaled boot image heador\n");
|
|
return -1;
|
|
}
|
|
|
|
if (hdr->page_size != page_size) {
|
|
dprintf(CRITICAL, "ERROR: Invaled boot image pagesize. Device pagesize: %d, Image pagesize: %d\n",page_size,hdr->page_size);
|
|
return -1;
|
|
}
|
|
|
|
n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);
|
|
if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {
|
|
dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
|
|
return -1;
|
|
}
|
|
offset += n;
|
|
|
|
n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
|
|
if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, n)) {
|
|
dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
|
|
return -1;
|
|
}
|
|
offset += n;
|
|
|
|
dprintf(INFO, "kernel @ %x (%d bytes)\n", hdr->kernel_addr,
|
|
hdr->kernel_size);
|
|
dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,
|
|
hdr->ramdisk_size);
|
|
|
|
if(hdr->cmdline[0]){
|
|
cmdline = (char*) hdr->cmdline;
|
|
} else {
|
|
cmdline = "";
|
|
}
|
|
strcat(cmdline," clk=");
|
|
strcat(cmdline,PSUEDO_VERSION);
|
|
/* TODO: create/pass atags to kernel */
|
|
dprintf(INFO, "cmdline = '%s'\n", cmdline);
|
|
|
|
dprintf(INFO, "Booting Linux\n");
|
|
boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR,
|
|
(const char *) cmdline, board_machtype(),
|
|
(void *)hdr->ramdisk_addr, hdr->ramdisk_size);
|
|
return 0;
|
|
}
|
|
|
|
void cmd_boot(const char *arg, void *data, unsigned sz)
|
|
{
|
|
unsigned kernel_actual;
|
|
unsigned ramdisk_actual;
|
|
static struct boot_img_hdr hdr;
|
|
char *ptr = ((char*) data);
|
|
|
|
if (sz < sizeof(hdr)) {
|
|
fastboot_fail("invalid bootimage header");
|
|
return;
|
|
}
|
|
|
|
memcpy(&hdr, data, sizeof(hdr));
|
|
|
|
/* ensure commandline is terminated */
|
|
hdr.cmdline[BOOT_ARGS_SIZE-1] = 0;
|
|
|
|
if(target_is_emmc_boot() && hdr.page_size) {
|
|
page_size = hdr.page_size;
|
|
page_mask = page_size - 1;
|
|
}
|
|
|
|
kernel_actual = ROUND_TO_PAGE(hdr.kernel_size, page_mask);
|
|
ramdisk_actual = ROUND_TO_PAGE(hdr.ramdisk_size, page_mask);
|
|
|
|
//cedesmith: this will prevent lk booting lk.bin
|
|
//if (page_size + kernel_actual + ramdisk_actual < sz) {
|
|
// fastboot_fail("incomplete bootimage");
|
|
// return;
|
|
//}
|
|
|
|
memmove((void*) KERNEL_ADDR, ptr + page_size, hdr.kernel_size);
|
|
memmove((void*) RAMDISK_ADDR, ptr + page_size + kernel_actual, hdr.ramdisk_size);
|
|
|
|
fastboot_okay("Booting linux.");
|
|
target_battery_charging_enable(0, 1);
|
|
udc_stop();
|
|
|
|
boot_linux((void*) KERNEL_ADDR, (void*) TAGS_ADDR,
|
|
(const char*) hdr.cmdline, board_machtype(),
|
|
(void*) RAMDISK_ADDR, hdr.ramdisk_size);
|
|
}
|
|
|
|
void cmd_erase(const char *arg, void *data, unsigned sz)
|
|
{
|
|
struct ptentry *ptn;
|
|
struct ptable *ptable;
|
|
|
|
ptable = flash_get_ptable();
|
|
if (ptable == NULL) {
|
|
fastboot_fail("partition table doesn't exist");
|
|
return;
|
|
}
|
|
|
|
ptn = ptable_find(ptable, arg);
|
|
if (ptn == NULL) {
|
|
fastboot_fail("unknown partition name");
|
|
return;
|
|
}
|
|
|
|
if (flash_erase(ptn)) {
|
|
fastboot_fail("failed to erase partition");
|
|
return;
|
|
}
|
|
fastboot_okay("Partition Erased successfully");
|
|
}
|
|
|
|
|
|
void cmd_erase_mmc(const char *arg, void *data, unsigned sz)
|
|
{
|
|
unsigned long long ptn = 0;
|
|
unsigned int out[512] = {0};
|
|
|
|
ptn = mmc_ptn_offset((unsigned char *)arg);
|
|
if(ptn == 0) {
|
|
fastboot_fail("partition table doesn't exist");
|
|
return;
|
|
}
|
|
|
|
/* Simple inefficient version of erase. Just writing
|
|
0 in first block */
|
|
if (mmc_write(ptn , 512, (unsigned int *)out)) {
|
|
fastboot_fail("failed to erase partition");
|
|
return;
|
|
}
|
|
fastboot_okay("MMC erased successfully.");
|
|
}
|
|
|
|
|
|
void cmd_flash_mmc(const char *arg, void *data, unsigned sz)
|
|
{
|
|
unsigned long long ptn = 0;
|
|
unsigned long long size = 0;
|
|
|
|
ptn = mmc_ptn_offset((unsigned char *)arg);
|
|
if(ptn == 0) {
|
|
fastboot_fail("partition table doesn't exist");
|
|
return;
|
|
}
|
|
|
|
if (!strcmp(arg, "boot") || !strcmp(arg, "recovery")) {
|
|
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
|
|
fastboot_fail("image is not a boot image");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
size = mmc_ptn_size((unsigned char *)arg);
|
|
if (ROUND_TO_PAGE(sz,511) > size) {
|
|
fastboot_fail("size too large");
|
|
return;
|
|
}
|
|
|
|
|
|
if (mmc_write(ptn , sz, (unsigned int *)data)) {
|
|
fastboot_fail("flash write failure");
|
|
return;
|
|
}
|
|
fastboot_okay("MMC Partition Update successful");
|
|
return;
|
|
}
|
|
|
|
void cmd_flash(const char *arg, void *data, unsigned sz)
|
|
{
|
|
struct ptentry *ptn;
|
|
struct ptable *ptable;
|
|
unsigned extra = 0;
|
|
|
|
ptable = flash_get_ptable();
|
|
if (ptable == NULL) {
|
|
fastboot_fail("partition table doesn't exist");
|
|
return;
|
|
}
|
|
|
|
ptn = ptable_find(ptable, arg);
|
|
if (ptn == NULL) {
|
|
fastboot_fail("unknown partition name");
|
|
return;
|
|
}
|
|
|
|
if (!strcmp(ptn->name, "boot") || !strcmp(ptn->name, "recovery") || !strcmp(ptn->name, "sboot")) {
|
|
if (memcmp((void *)data, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
|
|
fastboot_fail("image is not a boot image");
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!strcmp(ptn->name, "system") || !strcmp(ptn->name, "userdata")
|
|
|| !strcmp(ptn->name, "persist"))
|
|
extra = ((page_size >> 9) * 16);
|
|
else
|
|
sz = ROUND_TO_PAGE(sz, page_mask);
|
|
|
|
dprintf(INFO, "writing %d bytes to '%s'\n", sz, ptn->name);
|
|
if (flash_write(ptn, extra, data, sz)) {
|
|
fastboot_fail("flash write failure");
|
|
return;
|
|
}
|
|
dprintf(INFO, "partition '%s' updated\n", ptn->name);
|
|
fastboot_okay("Partition Update Successful.");
|
|
}
|
|
|
|
void cmd_continue(const char *arg, void *data, unsigned sz)
|
|
{
|
|
fastboot_okay("Initiating normal Routine.");
|
|
target_battery_charging_enable(0, 1);
|
|
udc_stop();
|
|
if (target_is_emmc_boot())
|
|
{
|
|
//boot_linux_from_mmc();
|
|
}
|
|
else
|
|
{
|
|
boot_linux_from_flash();
|
|
}
|
|
}
|
|
|
|
void cmd_reboot(const char *arg, void *data, unsigned sz)
|
|
{
|
|
dprintf(INFO, "rebooting the device\n");
|
|
fastboot_okay("Rebooting Device.");
|
|
reboot_device(0);
|
|
}
|
|
|
|
void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)
|
|
{
|
|
dprintf(INFO, "rebooting the device\n");
|
|
fastboot_okay("Rebooting Device to HBOOT.");
|
|
reboot_device(FASTBOOT_MODE);
|
|
}
|
|
void fastboot_okay(const char *info);
|
|
void fastboot_fail(const char *reason);
|
|
int fastboot_write(void *buf, unsigned len);
|
|
void fastboot_register(const char *prefix, void (*handle)(const char *arg, void *data, unsigned sz));
|
|
|
|
char charVal(char c)
|
|
{
|
|
c&=0xf;
|
|
if(c<=9) return '0'+c;
|
|
return 'A'+(c-10);
|
|
}
|
|
|
|
void send_mem(char* start, int len)
|
|
{
|
|
char response[64];
|
|
while(len>0)
|
|
{
|
|
int slen = len > 29 ? 29 : len;
|
|
memcpy(response, "INFO", 4);
|
|
response[4]=slen;
|
|
|
|
for(int i=0; i<slen; i++)
|
|
{
|
|
response[5+i*2] = charVal(start[i]>>4);
|
|
response[5+i*2+1]= charVal(start[i]);
|
|
}
|
|
response[5+slen*2+1]=0;
|
|
fastboot_write(response, 5+slen*2);
|
|
|
|
start+=slen;
|
|
len-=slen;
|
|
}
|
|
}
|
|
|
|
void cmd_oem_smesg()
|
|
{
|
|
send_mem((char*)0x1fe00018, MIN(0x200000, readl(0x1fe00000)));
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_dmesg()
|
|
{
|
|
if(*((unsigned*)0x2FFC0000) == 0x43474244 /* DBGC */ ) //see ram_console_buffer in kernel ram_console.c
|
|
{
|
|
send_mem((char*)0x2FFC000C, *((unsigned*)0x2FFC0008));
|
|
}
|
|
fastboot_okay("");
|
|
}
|
|
|
|
int str2u(const char *x)
|
|
{
|
|
while(*x==' ')x++;
|
|
|
|
unsigned base=10;
|
|
int sign=1;
|
|
unsigned n = 0;
|
|
|
|
if(strstr(x,"-")==x) { sign=-1; x++;};
|
|
if(strstr(x,"0x")==x) {base=16; x+=2;}
|
|
|
|
while(*x) {
|
|
char d=0;
|
|
switch(*x) {
|
|
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
|
|
d = *x - '0';
|
|
break;
|
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
d = (*x - 'a' + 10);
|
|
break;
|
|
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
|
d = (*x - 'A' + 10);
|
|
break;
|
|
default:
|
|
return sign*n;
|
|
}
|
|
if(d>=base) return sign*n;
|
|
n*=base;n+=d;
|
|
x++;
|
|
}
|
|
|
|
return sign*n;
|
|
}
|
|
void cmd_oem_dumpmem(const char *arg)
|
|
{
|
|
char *sStart = strtok((char*)arg, " ");
|
|
char *sLen = strtok(NULL, " ");
|
|
if(sStart==NULL || sLen==NULL)
|
|
{
|
|
fastboot_fail("usage:oem dump start len");
|
|
return;
|
|
}
|
|
|
|
send_mem((char*)str2u(sStart), str2u(sLen));
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_set(const char *arg)
|
|
{
|
|
char type=*arg; arg++;
|
|
char *sAddr = strtok((char*) arg, " ");
|
|
char *sVal = strtok(NULL, "\0");
|
|
if(sAddr==NULL || sVal==NULL)
|
|
{
|
|
fastboot_fail("usage:oem set[s,c,w] address value");
|
|
return;
|
|
}
|
|
char buff[64];
|
|
switch(type)
|
|
{
|
|
case 's':
|
|
memcpy((void*)str2u(sAddr), sVal, strlen(sVal));
|
|
send_mem((char*)str2u(sAddr), strlen(sVal));
|
|
break;
|
|
case 'c':
|
|
*((char*)str2u(sAddr)) = (char)str2u(sVal);
|
|
sprintf(buff, "%x", *((char*)str2u(sAddr)));
|
|
send_mem(buff, strlen(buff));
|
|
break;
|
|
case 'w':
|
|
default:
|
|
*((int*)str2u(sAddr)) = str2u(sVal);
|
|
sprintf(buff, "%x", *((int*)str2u(sAddr)));
|
|
send_mem(buff, strlen(buff));
|
|
}
|
|
fastboot_okay("");
|
|
}
|
|
void cmd_oem_cls(){
|
|
redraw_menu();
|
|
selector_enable();
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_part_add(const char *arg){
|
|
vpart_add(arg);
|
|
vpart_list();
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_part_resize(const char *arg){
|
|
vpart_resize(arg);
|
|
vpart_list();
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_part_del(const char *arg){
|
|
vpart_del(arg);
|
|
vpart_list();
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_part_commit(){
|
|
vpart_commit();
|
|
printf("\n Partition changes saved! Will Reboot device in 2 secs\n");
|
|
fastboot_okay("");
|
|
thread_sleep(1980);
|
|
reboot_device(FASTBOOT_MODE);
|
|
}
|
|
|
|
void cmd_oem_part_read(){
|
|
vpart_read();
|
|
vpart_list();
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_part_list(){
|
|
vpart_list();
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_part_clear(){
|
|
vpart_clear();
|
|
|
|
vpart_list();
|
|
fastboot_okay("");
|
|
}
|
|
|
|
void cmd_oem_part_create_default(){
|
|
vpart_clear();
|
|
vpart_create_default();
|
|
|
|
vpart_list();
|
|
fastboot_okay("");
|
|
}
|
|
void prnt_nand_stat(void)
|
|
{
|
|
struct flash_info *flash_info;
|
|
flash_info = flash_get_info();
|
|
unsigned start_block=0;
|
|
//unsigned vpt_start_block;
|
|
unsigned nand_num_blocks;
|
|
unsigned extrom_offset; // Space allocated by ExtROM and si backup on WinCE - Used as cache partition
|
|
unsigned extrom_size = 191 ; // 191 blocks = ~24 Mb
|
|
nand_num_blocks = flash_info->num_blocks;
|
|
blk_pmb = (1024*1024)/flash_info->block_size; // Number of blocks per 1Mb
|
|
// Offset for partition with part table
|
|
extrom_offset = nand_num_blocks - extrom_size; // Extrom start offset NAND Size - 24Mb
|
|
// Usable permanent flash storage - Complete size with extrom
|
|
flash_size_blk =(nand_num_blocks - start_block); // Max available flash size for user partitions
|
|
start_block = 0x219;
|
|
dprintf(INFO,"\n==============================================================================\n\n");
|
|
dprintf(INFO," Full flash size: %i blocks - %i Mb\n",nand_num_blocks, (int)(nand_num_blocks/blk_pmb));
|
|
dprintf(INFO," Usable flash size: %i blocks - %i Mb\n",flash_size_blk, (int)(flash_size_blk/blk_pmb));
|
|
dprintf(INFO," Flash ExtROM: offset:%x blocks:%i size:%i\n",extrom_offset, extrom_size, (int)(extrom_size/blk_pmb));
|
|
dprintf(INFO," Flash spare size: %i\n",flash_info->spare_size);
|
|
dprintf(INFO," Flash offset: %x\n",start_block);
|
|
dprintf(INFO," Partition table offset:%x size:%x\n",0x216, 2);
|
|
dprintf(INFO,"\n==============================================================================\n\n");
|
|
}
|
|
void cmd_oem_nand_status(void)
|
|
{
|
|
prnt_nand_stat();
|
|
fastboot_okay("");
|
|
}
|
|
void cmd_oem_part_format_all(){
|
|
|
|
struct ptentry *ptn;
|
|
struct ptable *ptable;
|
|
ptable = flash_get_vptable();
|
|
|
|
printf("\n\n\nInitializing flash format...\n");
|
|
|
|
if (ptable == NULL) {
|
|
printf( "ERROR: VPTABLE not found!!!\n");
|
|
return;
|
|
}
|
|
ptn = ptable_find(ptable, "task29");
|
|
|
|
if (ptn == NULL) {
|
|
printf( "ERROR: No vptable partition!!!\n");
|
|
return;
|
|
}
|
|
printf("Formating flash...\n");
|
|
|
|
printf("\n==============================================================================\n\n");
|
|
|
|
flash_erase(ptn);
|
|
|
|
printf("\n==============================================================================\n\n");
|
|
|
|
printf("\nFormat complete ! \nReboot device to create default partition table, or create partitions manualy!\n\n");
|
|
|
|
fastboot_okay("");
|
|
}
|
|
|
|
|
|
void cmd_oem_part_format_vpart(){
|
|
|
|
struct ptentry *ptn;
|
|
struct ptable *ptable;
|
|
ptable = flash_get_vptable();
|
|
|
|
printf("\n\n\nInitializing flash format...\n");
|
|
|
|
if (ptable == NULL) {
|
|
printf( "ERROR: VPTABLE not found!!!\n");
|
|
return;
|
|
}
|
|
ptn = ptable_find(ptable, "vptable");
|
|
|
|
if (ptn == NULL) {
|
|
printf( "ERROR: No vptable partition!!!\n");
|
|
return;
|
|
}
|
|
|
|
printf("Formating vptable...\n");
|
|
|
|
printf("\n==============================================================================\n\n");
|
|
|
|
flash_erase(ptn);
|
|
|
|
printf("\n==============================================================================\n\n");
|
|
|
|
printf("\nFormat complete ! \nReboot device to create default partition table, or create partitions manualy!\n\n");
|
|
|
|
|
|
fastboot_okay("");
|
|
return;
|
|
}
|
|
|
|
void cmd_test()
|
|
{
|
|
int i =0;
|
|
for (i=0;i<100;i++){
|
|
printf("Test line... %i\n", i);
|
|
}
|
|
fastboot_okay("Hello!");
|
|
redraw_menu();
|
|
selector_enable();
|
|
}
|
|
|
|
void cmd_oem_help(){
|
|
fbcon_resetdisp();
|
|
|
|
printf("\n================================ FASTBOOT HELP ================================\n");
|
|
|
|
printf(" fastboot oem help\n");
|
|
printf(" - This simple help\n\n");
|
|
|
|
printf(" fastboot oem cls\n");
|
|
printf(" - Clear screen\n\n");
|
|
|
|
printf(" fastboot oem part-add name:size\n");
|
|
printf(" - Create new partition with given name and size (in Mb, 0 for all space)\n");
|
|
printf(" - example: fastboot oem part-add system:160 - this will create system partition with size 160Mb\n\n");
|
|
|
|
|
|
printf(" fastboot oem part-resize name:size\n");
|
|
printf(" - Resize partition with given name to new size (in Mb, 0 for all space)\n");
|
|
printf(" - example: fastboot oem part-resize system:150 - this will resize system partition to 150Mb\n\n");
|
|
|
|
printf(" fastboot oem part-del name\n");
|
|
printf(" - Delete named partition\n\n");
|
|
|
|
printf(" fastboot oem part-create-default\n");
|
|
printf(" - Delete curent partition table and create default one\n\n");
|
|
|
|
printf(" fastboot oem part-read\n");
|
|
printf(" - Reload partition layout from NAND\n\n");
|
|
|
|
printf(" fastboot oem part-commit\n");
|
|
printf(" - Save curent layout to NAND. All changes to partition layout are tmp. untill commited to nand!\n\n");
|
|
|
|
printf(" fastboot oem part-list\n");
|
|
printf(" - Display current partition layout\n\n");
|
|
|
|
printf(" fastboot oem part-clear\n");
|
|
printf(" - Clear current partition layout\n\n");
|
|
|
|
printf(" fastboot oem format-all\n");
|
|
printf(" - WARNING !!! THIS COMMAND WILL FORMAT COMPLETE NAND (except bootloader)\n - ALSO IT WILL DISPLAY BAD SECTORS IF THERE ARE ANY\n");
|
|
printf(" - !!! THIS IS EQUIVALENT TO TASK 29 !!!\n\n");
|
|
|
|
fastboot_okay("Look at your Device.");
|
|
}
|
|
static int flashlight(void *arg){
|
|
volatile unsigned *bank6_in = (unsigned int*)(0xA9000864);
|
|
volatile unsigned *bank6_out = (unsigned int*)(0xA9000814);
|
|
for(;;){
|
|
*bank6_out = *bank6_in ^ 0x200000;
|
|
udelay(496);
|
|
if(keys_get_state_n(0x123)!=0)break;
|
|
}
|
|
thread_exit(0);
|
|
}
|
|
void cmd_flashlight(void){
|
|
thread_resume((thread_t *)thread_create("Flashlight", &flashlight, NULL, HIGHEST_PRIORITY, DEFAULT_STACK_SIZE));
|
|
return;
|
|
}
|
|
void cmd_oem(const char *arg, void *data, unsigned sz)
|
|
{
|
|
while(*arg==' ') arg++;
|
|
if(memcmp(arg, "cls", 3)==0) cmd_oem_cls();
|
|
if(memcmp(arg, "set", 3)==0) cmd_oem_set(arg+3);
|
|
if(memcmp(arg, "set", 3)==0) cmd_oem_set(arg+3);
|
|
if(memcmp(arg, "pwf ", 4)==0) cmd_oem_dumpmem(arg+4);
|
|
if(memcmp(arg, "test", 4)==0) cmd_test();
|
|
if(memcmp(arg, "dmesg", 5)==0) cmd_oem_dmesg();
|
|
if(memcmp(arg, "smesg", 5)==0) cmd_oem_smesg();
|
|
if(memcmp(arg, "nandstat", 8)==0) cmd_oem_nand_status();
|
|
if(memcmp(arg, "poweroff", 8)==0) cmd_powerdown(arg+8, data, sz);
|
|
if(memcmp(arg, "flashmmc ", 9)==0) cmd_flash_mmc(arg+9, data, sz);
|
|
if(memcmp(arg, "erasemmc ", 9)==0) cmd_erase_mmc(arg+9, data, sz);
|
|
if(memcmp(arg, "part-add ", 9)==0) cmd_oem_part_add(arg+9);
|
|
if(memcmp(arg, "part-del ", 9)==0) cmd_oem_part_del(arg+9);
|
|
if(memcmp(arg, "part-read", 9)==0) cmd_oem_part_read();
|
|
if(memcmp(arg, "part-list", 9)==0) cmd_oem_part_list();
|
|
if(memcmp(arg, "flashlight", 10)==0) cmd_flashlight();
|
|
if(memcmp(arg, "part-clear", 10)==0) cmd_oem_part_clear();
|
|
if(memcmp(arg, "format-all", 10)==0) cmd_oem_part_format_all();
|
|
if(memcmp(arg, "part-commit", 11)==0) cmd_oem_part_commit();
|
|
if(memcmp(arg, "part-resize ", 12)==0) cmd_oem_part_resize(arg+12);
|
|
if(memcmp(arg, "format-vpart", 12)==0) cmd_oem_part_format_vpart();
|
|
if(memcmp(arg, "part-create-default", 19)==0) cmd_oem_part_create_default();
|
|
if((memcmp(arg,"help",4)==0)||(memcmp(arg,"?",1)==0)) cmd_oem_help();
|
|
}
|
|
void target_init_fboot(void){
|
|
// Initiate Fastboot.
|
|
udc_init(&surf_udc_device);
|
|
fastboot_register("oem", cmd_oem);
|
|
fastboot_register("boot", cmd_boot);
|
|
fastboot_register("flash:", cmd_flash);
|
|
fastboot_register("erase:", cmd_erase);
|
|
fastboot_register("continue", cmd_continue);
|
|
fastboot_register("reboot", cmd_reboot);
|
|
fastboot_register("reboot-bootloader", cmd_reboot_bootloader);
|
|
fastboot_register("powerdown", cmd_powerdown);
|
|
fastboot_publish("version", "1.0");
|
|
fastboot_publish("version-bootloader", "1.0");
|
|
fastboot_publish("version-baseband", "unset");
|
|
fastboot_publish("serialno", "HTC HD2");
|
|
fastboot_publish("secure", "no");
|
|
fastboot_publish("product", TARGET(BOARD));
|
|
fastboot_publish("kernel", "lk");
|
|
fastboot_publish("author", "Shantanu Gupta, Danijel Posilovic, Arif Ali, Cedesmith, Qualcomm Innovation Centre, Travis Geiselbrecht.");
|
|
fastboot_init(target_get_scratch_address(),MEMBASE - SCRATCH_ADDR - 0x00100000);
|
|
udc_start();
|
|
target_battery_charging_enable(1, 0);
|
|
}
|
|
char ccharVal(char c)
|
|
{
|
|
c&=0xf;
|
|
if(c<=9) return '0'+c;
|
|
return 'A'+(c-10);
|
|
}
|
|
void dump_mem(char* start, int len)
|
|
{
|
|
char response[64];
|
|
while(len>0)
|
|
{
|
|
int slen = len > 29 ? 29 : len;
|
|
memcpy(response, "INF ", 4);
|
|
response[4]=slen;
|
|
|
|
for(int i=0; i<slen; i++)
|
|
{
|
|
response[5+i*2] = ccharVal(start[i]>>4);
|
|
response[5+i*2+1]= ccharVal(start[i]);
|
|
}
|
|
response[5+slen*2+1]=0;
|
|
_dputs(response);
|
|
start+=slen;
|
|
len-=slen;
|
|
}
|
|
_dputs("\n");
|
|
}
|
|
static int update_amss_str(void *arg)
|
|
{
|
|
while(!(strlen(amss_ver))){update_radio_ver();}
|
|
fbcon_resetdisp();
|
|
draw_clk_header();
|
|
redraw_menu();
|
|
selector_enable();
|
|
thread_exit(0);
|
|
return 0; /* LOL, is it even possible ? */
|
|
}
|
|
void aboot_init(const struct app_descriptor *app)
|
|
{
|
|
if (target_is_emmc_boot())
|
|
{
|
|
page_size = 2048;
|
|
page_mask = page_size - 1;
|
|
}
|
|
else
|
|
{
|
|
page_size = flash_page_size();
|
|
page_mask = page_size - 1;
|
|
}
|
|
/* Check if we should do something other than booting up */
|
|
if (keys_get_state(keys[6]) != 0)
|
|
boot_into_recovery = 1;
|
|
if (keys_get_state(keys[5]) != 0)
|
|
goto bmenu;
|
|
if (keys_get_state(keys[2]) != 0){
|
|
display_init();
|
|
}
|
|
if (check_reboot_mode() == RECOVERY_MODE) {
|
|
boot_into_recovery = 1;
|
|
} else if(check_reboot_mode() == FASTBOOT_MODE) {
|
|
goto bmenu;
|
|
}
|
|
if(boot_into_recovery == 1) {
|
|
recovery_init();
|
|
}
|
|
/* Environment setup for continuing, Lets boot if we can */
|
|
boot_linux_from_flash();
|
|
/* Couldn't Find anything to do (OR) User pressed Back Key. Load Menu */
|
|
bmenu:
|
|
{
|
|
thread_resume(thread_create("amss", &update_amss_str, NULL, LOW_PRIORITY, DEFAULT_STACK_SIZE));
|
|
display_init();
|
|
target_init_fboot();
|
|
init_menu();
|
|
}
|
|
}
|
|
APP_START(aboot).init = aboot_init,APP_END
|