rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (c) 2016 MediaTek Inc. |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining |
| 5 | * a copy of this software and associated documentation files |
| 6 | * (the "Software"), to deal in the Software without restriction, |
| 7 | * including without limitation the rights to use, copy, modify, merge, |
| 8 | * publish, distribute, sublicense, and/or sell copies of the Software, |
| 9 | * and to permit persons to whom the Software is furnished to do so, |
| 10 | * subject to the following conditions: |
| 11 | * |
| 12 | * The above copyright notice and this permission notice shall be |
| 13 | * included in all copies or substantial portions of the Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
| 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 22 | */ |
| 23 | |
| 24 | #include <dev/udc.h> |
| 25 | #include <lib/bio.h> |
| 26 | #include <lib/dl_commands.h> |
| 27 | #include <lib/fastboot.h> |
| 28 | #include <lib/fastboot_oem_cmd.h> |
| 29 | #include <lib/mempool.h> |
| 30 | #include <platform/mtk_serial_key.h> |
| 31 | #include <platform/mtk_wdt.h> |
| 32 | #include <reg.h> |
| 33 | #include <stdio.h> |
| 34 | #include <string.h> |
| 35 | #include <target/cust_usb.h> |
| 36 | |
| 37 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
| 38 | #ifndef SN_BUF_LEN |
| 39 | #define SN_BUF_LEN 19 /* fastboot use 13 bytes as default, max is 19 */ |
| 40 | #endif |
| 41 | #define DEFAULT_SERIAL_NUM "0123456789ABCDEF" |
| 42 | char sn_buf[SN_BUF_LEN+1] = DEFAULT_SERIAL_NUM; |
| 43 | |
| 44 | static struct udc_device surf_udc_device = { |
| 45 | .vendor_id = USB_VENDORID, |
| 46 | .product_id = USB_PRODUCTID, |
| 47 | .version_id = USB_VERSIONID, |
| 48 | .manufacturer = USB_MANUFACTURER, |
| 49 | .product = USB_PRODUCT_NAME, |
| 50 | }; |
| 51 | |
| 52 | static void register_commands(void) |
| 53 | { |
| 54 | fastboot_register("getvar:", cmd_getvar); |
| 55 | fastboot_register("download:", cmd_download); |
| 56 | fastboot_register("flash:", cmd_flash); |
| 57 | fastboot_register("erase:", cmd_erase); |
| 58 | fastboot_register("reboot", cmd_reboot); |
| 59 | fastboot_register("reboot-bootloader", cmd_reboot_bootloader); |
| 60 | fastboot_register("reboot-fastboot", cmd_reboot_fastbootd); |
| 61 | fastboot_register("oem reboot-recovery", cmd_reboot_recovery); |
| 62 | fastboot_register("oem continue", cmd_continue_boot); |
| 63 | #ifdef AVB_ENABLE_DEVICE_STATE_CHANGE |
| 64 | fastboot_register("flashing", cmd_flashing); |
| 65 | #endif |
| 66 | } |
| 67 | |
| 68 | static void register_oem_fastboot_cmds(void) |
| 69 | { |
| 70 | extern const struct fastboot_oem_cmd_descriptor __fb_oem_cmd_start[]; |
| 71 | extern const struct fastboot_oem_cmd_descriptor __fb_oem_cmd_end[]; |
| 72 | |
| 73 | const struct fastboot_oem_cmd_descriptor *cmd; |
| 74 | |
| 75 | for (cmd = __fb_oem_cmd_start; cmd != __fb_oem_cmd_end; cmd++) { |
| 76 | if (cmd->cmd_handler) |
| 77 | fastboot_register(cmd->cmd_str, cmd->cmd_handler); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | static void publish_attributes(void) |
| 82 | { |
| 83 | char buffer_size[11]; |
| 84 | sprintf(buffer_size, "0x%x", SCRATCH_SIZE); |
| 85 | fastboot_publish("version", "0.5"); |
| 86 | fastboot_publish("max-download-size", buffer_size); |
| 87 | fastboot_publish("is-userspace", "no"); |
| 88 | } |
| 89 | |
| 90 | static void storage_init(void) |
| 91 | { |
| 92 | /* init storage that only use in fastboot, currently none */ |
| 93 | bio_dump_devices(); |
| 94 | } |
| 95 | |
| 96 | static char udc_chr[32] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ456789"}; |
| 97 | static int get_serial(u64 hwkey, u32 chipid, char *ser) |
| 98 | { |
| 99 | u16 hashkey[4]; |
| 100 | u32 idx, ser_idx; |
| 101 | |
| 102 | /* split to 4 key with 16-bit width each */ |
| 103 | for (idx = 0; idx < ARRAY_SIZE(hashkey); idx++) { |
| 104 | hashkey[idx] = (u16)(hwkey & 0xffff); |
| 105 | hwkey >>= 16; |
| 106 | } |
| 107 | |
| 108 | /* hash the key with chip id */ |
| 109 | for (idx = 0; idx < ARRAY_SIZE(hashkey); idx++) { |
| 110 | u32 digit = (chipid % 10); |
| 111 | hashkey[idx] = (hashkey[idx] >> digit) | (hashkey[idx] << (16-digit)); |
| 112 | chipid = (chipid / 10); |
| 113 | } |
| 114 | |
| 115 | /* generate serail using hashkey */ |
| 116 | ser_idx = 0; |
| 117 | for (idx = 0; idx < ARRAY_SIZE(hashkey); idx++) { |
| 118 | ser[ser_idx++] = (hashkey[idx] & 0x001f); |
| 119 | ser[ser_idx++] = (hashkey[idx] & 0x00f8) >> 3; |
| 120 | ser[ser_idx++] = (hashkey[idx] & 0x1f00) >> 8; |
| 121 | ser[ser_idx++] = (hashkey[idx] & 0xf800) >> 11; |
| 122 | } |
| 123 | |
| 124 | for (idx = 0; idx < ser_idx; idx++) |
| 125 | ser[idx] = udc_chr[(int)ser[idx]]; |
| 126 | |
| 127 | ser[ser_idx] = 0x00; |
| 128 | |
| 129 | return 0; |
| 130 | } |
| 131 | |
| 132 | void ext_boot(void) |
| 133 | { |
| 134 | void *scratch_buf; |
| 135 | |
| 136 | u64 key = ((u64)readl(SERIAL_KEY_HI) << 32) | readl(SERIAL_KEY_LO); |
| 137 | if (key != 0) |
| 138 | get_serial(key, MACH_TYPE, sn_buf); |
| 139 | |
| 140 | surf_udc_device.serialno = sn_buf; |
| 141 | udc_init(&surf_udc_device); |
| 142 | |
| 143 | storage_init(); |
| 144 | mtk_wdt_disable(); |
| 145 | register_commands(); |
| 146 | register_oem_fastboot_cmds(); |
| 147 | publish_attributes(); |
| 148 | |
| 149 | scratch_buf = mempool_alloc(SCRATCH_SIZE, MEMPOOL_ANY); |
| 150 | |
| 151 | if (!scratch_buf) |
| 152 | return; |
| 153 | |
| 154 | fastboot_init(scratch_buf, (unsigned long long)SCRATCH_SIZE); |
| 155 | mempool_free(scratch_buf); |
| 156 | } |