diff --git a/bin/oem_filter.exe b/bin/oem_filter.exe new file mode 100644 index 0000000..1dcc3f7 Binary files /dev/null and b/bin/oem_filter.exe differ diff --git a/bin/oemcmd.bat b/bin/oemcmd.bat new file mode 100644 index 0000000..a66115e --- /dev/null +++ b/bin/oemcmd.bat @@ -0,0 +1 @@ +@fastboot oem %* 2>&1 | oem_filter \ No newline at end of file diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..ceb3d84 --- /dev/null +++ b/changelog.txt @@ -0,0 +1,10 @@ +1.3.2 + - ROMHDR base addr is spl virtual 0x80000000 = 11800000 physical, LK will relocate to correct address (MEMBASE) + - save reboot reason at 0x2FFB0000 (ramconsole - 0x1000 (PAGE_SIZE)) and @0x2FFB0004 XOR 0x004b4c63 (cLK signature) + - added oem cmd to fastboot and oemcmd.bat for PC. supported commands are: + dmesg - kernel debug messages + smesg - spl messages + pwf addr len - dump memory + set[c,w,s] addr value - set char(1byte), word(4 byes), or string + + \ No newline at end of file diff --git a/lk/app/aboot/fastboot.c b/lk/app/aboot/fastboot.c index 0e0bde6..c449a79 100644 --- a/lk/app/aboot/fastboot.c +++ b/lk/app/aboot/fastboot.c @@ -228,23 +228,15 @@ void fastboot_okay(const char *info) fastboot_ack("OKAY", info); } +int fastboot_write(void *buf, unsigned len) +{ + return usb_write(buf, len); +} + static void cmd_getvar(const char *arg, void *data, unsigned sz) { struct fastboot_var *var; - if(!strcmp(arg,"dmesg")) - { - char response[64]; - for(char* c=(char*) 0x2FFC0000; c<(char*)(0x2FFC0000+0x00040000); c+=59) - { - memcpy(response, "INFO",4);memcpy(response+4, c, 59); response[63]=0; - //snprintf(response, 64, "%s%s", "INFO", c); - usb_write(response, 64); - } - fastboot_okay(""); - return; - } - for (var = varlist; var; var = var->next) { if (!strcmp(var->name, arg)) { fastboot_okay(var->value); diff --git a/lk/target/htcleo/init.c b/lk/target/htcleo/init.c index d1a4269..3f6be43 100644 --- a/lk/target/htcleo/init.c +++ b/lk/target/htcleo/init.c @@ -24,6 +24,10 @@ static struct ptentry board_part_list[MAX_PTABLE_PARTS] __attribute__ ((aligned { .name = "PTABLE-MB", // PTABLE-BLK or PTABLE-MB for length in MB or BLOCKS }, + { + .name = "misc", + .length = 1 /* In MB */, + }, { .name = "recovery", .length = 5 /* In MB */, @@ -96,6 +100,7 @@ void cmd_dmesg(const char *arg, void *data, unsigned sz); void reboot(unsigned reboot_reason); void target_display_init(); unsigned get_boot_reason(void); +void cmd_oem_register(); void target_init(void) { struct flash_info *flash_info; @@ -180,6 +185,7 @@ void display_lk_version() { _dputs("cedesmith's LK (CLK) v1.3\n"); } +struct fbcon_config* fbcon_display(void); void htcleo_fastboot_init() { // off charge and recovery boot failed, reboot to normal mode @@ -192,6 +198,8 @@ void htcleo_fastboot_init() display_lk_version(); htcleo_ptable_dump(&flash_ptable); } + + cmd_oem_register(); } void target_early_init(void) { @@ -206,20 +214,37 @@ unsigned board_machtype(void) void reboot_device(unsigned reboot_reason) { + writel(reboot_reason, 0x2FFB0000); + writel(reboot_reason^0x004b4c63, 0x2FFB0004); //XOR with cLK signature reboot(reboot_reason); } unsigned boot_reason = 0xFFFFFFFF; +unsigned android_reboot_reason = 0; +unsigned check_reboot_mode(void); unsigned get_boot_reason(void) { if(boot_reason==0xFFFFFFFF) { boot_reason = readl(MSM_SHARED_BASE+0xef244); dprintf(INFO, "boot reason %x\n", boot_reason); + if(boot_reason==1 || boot_reason==6) + { + if(readl(0x2FFB0000)==(readl(0x2FFB0004)^0x004b4c63)) + { + android_reboot_reason = readl(0x2FFB0000); + dprintf(INFO, "android reboot reason %x\n", android_reboot_reason); + writel(0, 0x2FFB0000); + } + } } return boot_reason; } - +unsigned check_reboot_mode(void) +{ + get_boot_reason(); + return android_reboot_reason; +} unsigned target_pause_for_battery_charge(void) { diff --git a/lk/target/htcleo/oem_cmd.c b/lk/target/htcleo/oem_cmd.c new file mode 100644 index 0000000..7c2371b --- /dev/null +++ b/lk/target/htcleo/oem_cmd.c @@ -0,0 +1,148 @@ +/* + * License: GPL + * Author: cedesmith + */ +#include +#include +#include +#include + +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)); + +static char charVal(char c) +{ + c&=0xf; + if(c<=9) return '0'+c; + return 'A'+(c-10); +} + +static 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>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; + } +} + +static void cmd_oem_smesg() +{ + send_mem((char*)0x1fe00018, MIN(0x200000, readl(0x1fe00000))); + fastboot_okay(""); +} + +static 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(""); +} + +static 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; +} +static 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(""); +} +static 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(""); +} + +static void cmd_oem(const char *arg, void *data, unsigned sz) +{ + while(*arg==' ') arg++; + if(memcmp(arg, "dmesg", 5)==0) cmd_oem_dmesg(); + if(memcmp(arg, "smesg", 5)==0) cmd_oem_smesg(); + if(memcmp(arg, "pwf ", 4)==0) cmd_oem_dumpmem(arg+4); + if(memcmp(arg, "set", 3)==0) cmd_oem_set(arg+3); +} + +void cmd_oem_register() +{ + fastboot_register("oem", cmd_oem); +} diff --git a/lk/target/htcleo/rules.mk b/lk/target/htcleo/rules.mk index 7a51567..9c04170 100644 --- a/lk/target/htcleo/rules.mk +++ b/lk/target/htcleo/rules.mk @@ -5,30 +5,19 @@ INCLUDES += -I$(LOCAL_DIR)/include -I$(LK_TOP_DIR)/platform/msm_shared PLATFORM := qsd8k #define system partition size (in MB), if not defined my custom (from magldr) layout is used. see init.c -#DEFINES += SYSTEM_PARTITION_SIZE=150 +DEFINES += SYSTEM_PARTITION_SIZE=150 #DEFINES += SYSTEM_PARTITION_SIZE=250 #cedesmith note: MEMBASE requires edit in platform/qsd8k/rules.mk -#MEMBASE := 0x20000000 -#MEMBASE := 0x27000000 -#MEMBASE := 0x2E000000 -#MEMSIZE := 0x00800000 - # maximum partition size will be about 340mb ( MEMBASE-SCRATCH_ADDR) MEMBASE := 0x28000000 -MEMSIZE := 0x00100000 -#SPL virtual address where LK is loaded -#DEFINES += WSPL_VADDR=0x80000000 -#SPL 0x26600000=>0x95100000 so VADDR = (0x28000000-0x26600000)+0x95100000 -DEFINES += WSPL_VADDR=0x96B00000 -#SPL 0x28500000=>0x98B00000 - +MEMSIZE := 0x00100000 +DEFINES += WSPL_VADDR=0x80000000 BASE_ADDR := 0x11800000 TAGS_ADDR := "(BASE_ADDR+0x00000100)" KERNEL_ADDR := "(BASE_ADDR+0x00008000)" RAMDISK_ADDR := "(BASE_ADDR+0x00a00000)" -#SCRATCH_ADDR := "(BASE_ADDR+0x04000000)" SCRATCH_ADDR := "(BASE_ADDR+0x01400000)" #BASE_ADDR + 0x04000000 @@ -70,5 +59,6 @@ OBJS += \ OBJS += \ $(LOCAL_DIR)/htcleo_boot.o \ $(LOCAL_DIR)/htcleo_boot_s.o\ - $(LOCAL_DIR)/platform.o + $(LOCAL_DIR)/platform.o \ + $(LOCAL_DIR)/oem_cmd.o diff --git a/oem_filter.c b/oem_filter.c new file mode 100644 index 0000000..c3d1ff9 --- /dev/null +++ b/oem_filter.c @@ -0,0 +1,47 @@ +#include +#include + +unsigned char hexVal(char c) +{ + switch(c) + { + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + return c-'0'; + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return c - 'a' + 10; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + return c - 'A' + 10; + } + return 0; +} +int main() { + char buff[0x40000]; + + while(!feof(stdin) && fgetc(stdin)!='\n' ); + + while(!feof(stdin)) + { + size_t len = fread(buff, 1, 5, stdin); + int hLen = -1; + if(strncmp(buff, "INFO", 4)==0) hLen = buff[4]; + if(strncmp(buff, "(boot", 5)==0) + { + len += fread(buff+5, 1, 9, stdin); + if(strncmp(buff, "(bootloader) ", 13)==0) hLen = buff[13]; + } + if(hLen!=-1) + { + for(;hLen>0;hLen--) fputc(hexVal(fgetc(stdin))<<4 | hexVal(fgetc(stdin)), stdout); + fgetc(stdin);// read \n appended by fastboot + continue; + } + fwrite(buff, 1, len, stdout); + break; + } + + while(!feof(stdin)) + { + size_t len = fread(buff, 1, sizeof(buff), stdin); + fwrite(buff, 1, len, stdout); + } +} diff --git a/patches/cwm_off_charge.patch b/patches/cwm_off_charge.patch new file mode 100644 index 0000000..e9b08cf --- /dev/null +++ b/patches/cwm_off_charge.patch @@ -0,0 +1,41 @@ +diff --git a/extendedcommands.c b/extendedcommands.c +index 1ce3bf1..2562e6c 100644 +--- a/extendedcommands.c ++++ b/extendedcommands.c +@@ -1110,21 +1110,25 @@ int volume_main(int argc, char **argv) { + } + + void handle_chargemode() { ++ // old code to read /proc/cmdline was broken because file size is always 0 so file_data was always empty string + const char* filename = "/proc/cmdline"; +- struct stat file_info; +- if (0 != stat(filename, &file_info)) +- return; +- +- int file_len = file_info.st_size; +- char* file_data = (char*)malloc(file_len + 1); + FILE *file = fopen(filename, "rb"); + if (file == NULL) + return; +- fread(file_data, file_len, 1, file); +- // supposedly not necessary, but let's be safe. ++ char file_data[1024]; ++ int file_len=fread(file_data, 1, 1023, file); + file_data[file_len] = '\0'; + fclose(file); +- ++ + if (strstr(file_data, "androidboot.mode=offmode_charging") != NULL) +- reboot(RB_POWER_OFF); ++ { ++ // let recovery kernel charge the battery, reboot on any key press so Android will start as user would expect ++ ev_init(); ++ struct input_event ev; ++ do ++ { ++ ev_get(&ev, 0); ++ } while (ev.type != EV_KEY || ev.code > KEY_MAX); ++ reboot(RB_AUTOBOOT); ++ } + } +\ No newline at end of file diff --git a/patches/kernel_clk_power_collapse.patch b/patches/kernel_clk_power_collapse.patch new file mode 100644 index 0000000..23a4881 --- /dev/null +++ b/patches/kernel_clk_power_collapse.patch @@ -0,0 +1,32 @@ +diff --git a/arch/arm/mach-msm/board-htcleo.c b/arch/arm/mach-msm/board-htcleo.c +index e13205b..ee7680e 100644 +--- a/arch/arm/mach-msm/board-htcleo.c ++++ b/arch/arm/mach-msm/board-htcleo.c +@@ -87,6 +87,7 @@ static int __init parse_tag_nand_boot(const struct tag *tag) + { + struct tag_magldr_entry *mentry = (struct tag_magldr_entry *)(&tag->u); + nand_boot = !(unsigned int)mentry->fNoNandBoot; ++ if(*((unsigned*)&tag->u)==0x004b4c63) nand_boot = 2; // cLK signature + pr_info("Nand Boot: %d\n", nand_boot); + return 0; + } +diff --git a/arch/arm/mach-msm/pm.c b/arch/arm/mach-msm/pm.c +index 8766174..56ccb2a 100644 +--- a/arch/arm/mach-msm/pm.c ++++ b/arch/arm/mach-msm/pm.c +@@ -892,6 +892,15 @@ static int __init msm_pm_init(void) + register_reboot_notifier(&msm_reboot_notifier); + msm_pm_reset_vector = ioremap(0x0, PAGE_SIZE); + ++#if defined(CONFIG_MACH_HTCLEO) ++ // if cLK is bootloader 0x0 is protected and not writtable but cLK changed reset vecotr to jump at address stored at 0x11800004 ++ if(htcleo_is_nand_boot()==2){ ++ pr_info("msm_pm: 0x00000000: %x\n", msm_pm_reset_vector[0]); ++ pr_info("msm_pm: 0x00000004: %x\n", msm_pm_reset_vector[1]); ++ msm_pm_reset_vector = ioremap(0x11800000, PAGE_SIZE); ++ } ++#endif ++ + if (msm_pm_reset_vector == NULL) { + printk(KERN_ERR "msm_pm_init: failed to map reset vector\n"); + return -ENODEV; diff --git a/patches/kernel_off_mode_charging_panel_init_crash.patch b/patches/kernel_off_mode_charging_panel_init_crash.patch new file mode 100644 index 0000000..f3f0077 --- /dev/null +++ b/patches/kernel_off_mode_charging_panel_init_crash.patch @@ -0,0 +1,39 @@ +diff --git a/arch/arm/mach-msm/board-htcleo-panel.c b/arch/arm/mach-msm/board-htcleo-panel.c +index a7a701d..1b98611 100644 +--- a/arch/arm/mach-msm/board-htcleo-panel.c ++++ b/arch/arm/mach-msm/board-htcleo-panel.c +@@ -861,9 +861,17 @@ static void detect_panel_type(void) + } + else + { +- printk(" UNKNOWN, stop system now\n"); + htcleo_panel_type = PANELTYPE_UNKNOWN; +- BUG(); ++ extern int board_mfg_mode(void); ++ if(board_mfg_mode()==5) ++ { ++ printk(" offmode charging, panel is off\n"); ++ } ++ else ++ { ++ printk(" UNKNOWN, stop system now\n"); ++ BUG(); ++ } + } + } + +diff --git a/arch/arm/mach-msm/devices_htc.c b/arch/arm/mach-msm/devices_htc.c +index e5f65e7..6839c0d 100644 +--- a/arch/arm/mach-msm/devices_htc.c ++++ b/arch/arm/mach-msm/devices_htc.c +@@ -457,6 +457,10 @@ int __init board_mfg_mode_init(char *s) + mfg_mode = 2; + else if (!strcmp(s, "charge")) + mfg_mode = 3; ++ else if (!strcmp(s, "power_test")) ++ mfg_mode = 4; ++ else if (!strcmp(s, "offmode_charging")) ++ mfg_mode = 5; + + return 1; + } diff --git a/patches/kernel_reboot_reason.patch b/patches/kernel_reboot_reason.patch new file mode 100644 index 0000000..bba4455 --- /dev/null +++ b/patches/kernel_reboot_reason.patch @@ -0,0 +1,33 @@ +diff --git a/arch/arm/mach-msm/pm.c b/arch/arm/mach-msm/pm.c +index 56ccb2a..f3b17f2 100644 +--- a/arch/arm/mach-msm/pm.c ++++ b/arch/arm/mach-msm/pm.c +@@ -714,10 +714,28 @@ void msm_pm_flush_console(void) + release_console_sem(); + } + ++#if defined(CONFIG_MACH_HTCLEO) ++static void htcleo_save_reset_reason() ++{ ++ /* save restart_reason to be accesible in bootloader @ ramconsole - 0x1000*/ ++ uint32_t *bootloader_reset_reason = ioremap(0x2FFB0000, PAGE_SIZE); ++ if(bootloader_reset_reason!=NULL) ++ { ++ printk(KERN_INFO "msm_restart saving reason %x @ 0x2FFB0000 \n", restart_reason); ++ bootloader_reset_reason[0]=restart_reason; ++ bootloader_reset_reason[1]=restart_reason^0x004b4c63; //XOR with cLK signature so we know is not trash ++ } ++} ++#endif ++ + static void msm_pm_restart(char str) + { + msm_pm_flush_console(); + ++#if defined(CONFIG_MACH_HTCLEO) ++ htcleo_save_reset_reason(); ++#endif ++ + /* always reboot device through proc comm */ + if (restart_reason == 0x6f656d99) + msm_proc_comm(PCOM_RESET_CHIP_IMM, &restart_reason, 0); diff --git a/readme_boot.img.txt b/readme_boot.img.txt index c6574a4..8cdaef6 100644 --- a/readme_boot.img.txt +++ b/readme_boot.img.txt @@ -1,6 +1,7 @@ #compile kernel and make boot.img/recovery.img #make ARCH=arm CROSS_COMPILE=arm-none-eabi- mkbootimg --kernel zImage --ramdisk initrd.gz --cmdline "" --base 0x11800000 -o android_boot.img +mkbootimg --cmdline "" --base 0x11800000 --kernel zImage --ramdisk initrd.gz -o boot.img mkbootimg --base 0x11800000 --cmdline "no_console_suspend=0" --kernel zImage --ramdisk initrd.gz -o android_boot.img #create initrd.gz