| /* |
| * Copyright (c) 2016 MediaTek Inc. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files |
| * (the "Software"), to deal in the Software without restriction, |
| * including without limitation the rights to use, copy, modify, merge, |
| * publish, distribute, sublicense, and/or sell copies of the Software, |
| * and to permit persons to whom the Software is furnished to do so, |
| * subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #include <dev/udc.h> |
| #include <lib/bio.h> |
| #include <lib/dl_commands.h> |
| #include <lib/fastboot.h> |
| #include <lib/fastboot_oem_cmd.h> |
| #include <lib/mempool.h> |
| #include <platform/mtk_serial_key.h> |
| #include <platform/mtk_wdt.h> |
| #include <reg.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <target/cust_usb.h> |
| |
| #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
| #ifndef SN_BUF_LEN |
| #define SN_BUF_LEN 19 /* fastboot use 13 bytes as default, max is 19 */ |
| #endif |
| #define DEFAULT_SERIAL_NUM "0123456789ABCDEF" |
| char sn_buf[SN_BUF_LEN+1] = DEFAULT_SERIAL_NUM; |
| |
| static struct udc_device surf_udc_device = { |
| .vendor_id = USB_VENDORID, |
| .product_id = USB_PRODUCTID, |
| .version_id = USB_VERSIONID, |
| .manufacturer = USB_MANUFACTURER, |
| .product = USB_PRODUCT_NAME, |
| }; |
| |
| static void register_commands(void) |
| { |
| fastboot_register("getvar:", cmd_getvar); |
| fastboot_register("download:", cmd_download); |
| fastboot_register("flash:", cmd_flash); |
| fastboot_register("erase:", cmd_erase); |
| fastboot_register("reboot", cmd_reboot); |
| fastboot_register("reboot-bootloader", cmd_reboot_bootloader); |
| fastboot_register("reboot-fastboot", cmd_reboot_fastbootd); |
| fastboot_register("oem reboot-recovery", cmd_reboot_recovery); |
| fastboot_register("oem continue", cmd_continue_boot); |
| #ifdef AVB_ENABLE_DEVICE_STATE_CHANGE |
| fastboot_register("flashing", cmd_flashing); |
| #endif |
| } |
| |
| static void register_oem_fastboot_cmds(void) |
| { |
| extern const struct fastboot_oem_cmd_descriptor __fb_oem_cmd_start[]; |
| extern const struct fastboot_oem_cmd_descriptor __fb_oem_cmd_end[]; |
| |
| const struct fastboot_oem_cmd_descriptor *cmd; |
| |
| for (cmd = __fb_oem_cmd_start; cmd != __fb_oem_cmd_end; cmd++) { |
| if (cmd->cmd_handler) |
| fastboot_register(cmd->cmd_str, cmd->cmd_handler); |
| } |
| } |
| |
| static void publish_attributes(void) |
| { |
| char buffer_size[11]; |
| sprintf(buffer_size, "0x%x", SCRATCH_SIZE); |
| fastboot_publish("version", "0.5"); |
| fastboot_publish("max-download-size", buffer_size); |
| fastboot_publish("is-userspace", "no"); |
| } |
| |
| static void storage_init(void) |
| { |
| /* init storage that only use in fastboot, currently none */ |
| bio_dump_devices(); |
| } |
| |
| static char udc_chr[32] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ456789"}; |
| static int get_serial(u64 hwkey, u32 chipid, char *ser) |
| { |
| u16 hashkey[4]; |
| u32 idx, ser_idx; |
| |
| /* split to 4 key with 16-bit width each */ |
| for (idx = 0; idx < ARRAY_SIZE(hashkey); idx++) { |
| hashkey[idx] = (u16)(hwkey & 0xffff); |
| hwkey >>= 16; |
| } |
| |
| /* hash the key with chip id */ |
| for (idx = 0; idx < ARRAY_SIZE(hashkey); idx++) { |
| u32 digit = (chipid % 10); |
| hashkey[idx] = (hashkey[idx] >> digit) | (hashkey[idx] << (16-digit)); |
| chipid = (chipid / 10); |
| } |
| |
| /* generate serail using hashkey */ |
| ser_idx = 0; |
| for (idx = 0; idx < ARRAY_SIZE(hashkey); idx++) { |
| ser[ser_idx++] = (hashkey[idx] & 0x001f); |
| ser[ser_idx++] = (hashkey[idx] & 0x00f8) >> 3; |
| ser[ser_idx++] = (hashkey[idx] & 0x1f00) >> 8; |
| ser[ser_idx++] = (hashkey[idx] & 0xf800) >> 11; |
| } |
| |
| for (idx = 0; idx < ser_idx; idx++) |
| ser[idx] = udc_chr[(int)ser[idx]]; |
| |
| ser[ser_idx] = 0x00; |
| |
| return 0; |
| } |
| |
| void ext_boot(void) |
| { |
| void *scratch_buf; |
| |
| u64 key = ((u64)readl(SERIAL_KEY_HI) << 32) | readl(SERIAL_KEY_LO); |
| if (key != 0) |
| get_serial(key, MACH_TYPE, sn_buf); |
| |
| surf_udc_device.serialno = sn_buf; |
| udc_init(&surf_udc_device); |
| |
| storage_init(); |
| mtk_wdt_disable(); |
| register_commands(); |
| register_oem_fastboot_cmds(); |
| publish_attributes(); |
| |
| scratch_buf = mempool_alloc(SCRATCH_SIZE, MEMPOOL_ANY); |
| |
| if (!scratch_buf) |
| return; |
| |
| fastboot_init(scratch_buf, (unsigned long long)SCRATCH_SIZE); |
| mempool_free(scratch_buf); |
| } |