Commit 8cb9cd7e436a395ea772763c56788cb19e8c0b83
Committed by
Ji Luo
1 parent
a6ea228bd7
Exists in
smarc_8mq-imx_v2020.04_5.4.24_2.1.0
and in
1 other branch
MA-16457-2 support reboot-fastboot command in u-boot
Android implement the userspace fastboot in Android Recovery. Follow Google's spec, added below 2 fastboot command support: * fastboot getvar is-userspace * fastboot reboot fastboot TEST: fastboot commands. Change-Id: Ib6047413be0a45b3c00626cdb8594809eb8a2b6b Signed-off-by: Haoran.Wang <elven.wang@nxp.com> (cherry picked from commit 314bded076dfc3e544cc7094ce3f6c4c330be4dd)
Showing 7 changed files with 94 additions and 2 deletions Inline Diff
drivers/fastboot/fb_fsl/bcb.h
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. | 3 | * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #ifndef BCB_H | 6 | #ifndef BCB_H |
7 | #define BCB_H | 7 | #define BCB_H |
8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
9 | #include <linux/stat.h> | 9 | #include <linux/stat.h> |
10 | 10 | ||
11 | #define FASTBOOT_BCB_CMD "bootonce-bootloader" | 11 | #define FASTBOOT_BCB_CMD "bootonce-bootloader" |
12 | #ifdef CONFIG_ANDROID_RECOVERY | 12 | #ifdef CONFIG_ANDROID_RECOVERY |
13 | #define RECOVERY_BCB_CMD "boot-recovery" | 13 | #define RECOVERY_BCB_CMD "boot-recovery" |
14 | #define RECOVERY_FASTBOOT_ARG "recovery\n--fastboot" | ||
14 | #endif | 15 | #endif |
15 | /* keep same as bootable/recovery/bootloader.h */ | 16 | /* keep same as bootable/recovery/bootloader.h */ |
16 | struct bootloader_message { | 17 | struct bootloader_message { |
17 | char command[32]; | 18 | char command[32]; |
18 | char status[32]; | 19 | char status[32]; |
19 | char recovery[768]; | 20 | char recovery[768]; |
20 | 21 | ||
21 | /* The 'recovery' field used to be 1024 bytes. It has only ever | 22 | /* The 'recovery' field used to be 1024 bytes. It has only ever |
22 | been used to store the recovery command line, so 768 bytes | 23 | been used to store the recovery command line, so 768 bytes |
23 | should be plenty. We carve off the last 256 bytes to store the | 24 | should be plenty. We carve off the last 256 bytes to store the |
24 | stage string (for multistage packages) and possible future | 25 | stage string (for multistage packages) and possible future |
25 | expansion. */ | 26 | expansion. */ |
26 | char stage[32]; | 27 | char stage[32]; |
27 | 28 | ||
28 | /* The 'reserved' field used to be 224 bytes when it was initially | 29 | /* The 'reserved' field used to be 224 bytes when it was initially |
29 | carved off from the 1024-byte recovery field. Bump it up to | 30 | carved off from the 1024-byte recovery field. Bump it up to |
30 | 1184-byte so that the entire bootloader_message struct rounds up | 31 | 1184-byte so that the entire bootloader_message struct rounds up |
31 | to 2048-byte. | 32 | to 2048-byte. |
32 | */ | 33 | */ |
33 | char reserved[1184]; | 34 | char reserved[1184]; |
34 | }; | 35 | }; |
35 | 36 | ||
36 | struct bootloader_message_ab { | 37 | struct bootloader_message_ab { |
37 | struct bootloader_message message; | 38 | struct bootloader_message message; |
38 | char slot_suffix[32]; | 39 | char slot_suffix[32]; |
39 | 40 | ||
40 | /* Round up the entire struct to 4096-byte. */ | 41 | /* Round up the entire struct to 4096-byte. */ |
41 | char reserved[2016]; | 42 | char reserved[2016]; |
42 | }; | 43 | }; |
43 | 44 | ||
44 | /* start from bootloader_message_ab.slot_suffix[BOOTCTRL_IDX] */ | 45 | /* start from bootloader_message_ab.slot_suffix[BOOTCTRL_IDX] */ |
45 | #define BOOTCTRL_IDX 0 | 46 | #define BOOTCTRL_IDX 0 |
46 | #define MISC_COMMAND_IDX 0 | 47 | #define MISC_COMMAND_IDX 0 |
47 | #define BOOTCTRL_OFFSET \ | 48 | #define BOOTCTRL_OFFSET \ |
48 | (u32)(&(((struct bootloader_message_ab *)0)->slot_suffix[BOOTCTRL_IDX])) | 49 | (u32)(&(((struct bootloader_message_ab *)0)->slot_suffix[BOOTCTRL_IDX])) |
49 | #define MISC_COMMAND \ | 50 | #define MISC_COMMAND \ |
50 | (u32)(uintptr_t)(&(((struct bootloader_message *)0)->command[MISC_COMMAND_IDX])) | 51 | (u32)(uintptr_t)(&(((struct bootloader_message *)0)->command[MISC_COMMAND_IDX])) |
52 | |||
53 | #ifdef CONFIG_ANDROID_RECOVERY | ||
54 | #define RECOVERY_OPTIONS\ | ||
55 | (u32)(uintptr_t)(&(((struct bootloader_message *)0)->recovery[0])) | ||
56 | #endif | ||
51 | int bcb_rw_block(bool bread, char **ppblock, | 57 | int bcb_rw_block(bool bread, char **ppblock, |
52 | uint *pblksize, char *pblock_write, uint offset, uint size); | 58 | uint *pblksize, char *pblock_write, uint offset, uint size); |
53 | 59 | ||
54 | int bcb_write_command(char *bcb_command); | 60 | int bcb_write_command(char *bcb_command); |
55 | int bcb_read_command(char *command); | 61 | int bcb_read_command(char *command); |
56 | 62 | ||
63 | #ifdef CONFIG_ANDROID_RECOVERY | ||
64 | int bcb_write_recovery_opt(char *opts); | ||
65 | #endif | ||
57 | #endif | 66 | #endif |
58 | 67 |
drivers/fastboot/fb_fsl/command.c
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. | 3 | * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <common.h> | 6 | #include <common.h> |
7 | #include <g_dnl.h> | 7 | #include <g_dnl.h> |
8 | #include "bcb.h" | 8 | #include "bcb.h" |
9 | 9 | ||
10 | int bcb_read_command(char *command) | 10 | int bcb_read_command(char *command) |
11 | { | 11 | { |
12 | int ret = 0; | 12 | int ret = 0; |
13 | char *p_block = NULL; | 13 | char *p_block = NULL; |
14 | uint offset_in_block = 0; | 14 | uint offset_in_block = 0; |
15 | uint blk_size = 0; | 15 | uint blk_size = 0; |
16 | 16 | ||
17 | if (command == NULL) | 17 | if (command == NULL) |
18 | return -1; | 18 | return -1; |
19 | 19 | ||
20 | ret = bcb_rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); | 20 | ret = bcb_rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); |
21 | if (ret) { | 21 | if (ret) { |
22 | printf("read_bootctl, bcb_rw_block read failed\n"); | 22 | printf("read_bootctl, bcb_rw_block read failed\n"); |
23 | return -1; | 23 | return -1; |
24 | } | 24 | } |
25 | 25 | ||
26 | offset_in_block = MISC_COMMAND%blk_size; | 26 | offset_in_block = MISC_COMMAND%blk_size; |
27 | memcpy(command, p_block + offset_in_block, 32); | 27 | memcpy(command, p_block + offset_in_block, 32); |
28 | free(p_block); | 28 | free(p_block); |
29 | 29 | ||
30 | return 0; | 30 | return 0; |
31 | } | 31 | } |
32 | int bcb_write_command(char *bcb_command) | 32 | int bcb_write_command(char *bcb_command) |
33 | { | 33 | { |
34 | int ret = 0; | 34 | int ret = 0; |
35 | char *p_block = NULL; | 35 | char *p_block = NULL; |
36 | uint offset_in_block = 0; | 36 | uint offset_in_block = 0; |
37 | uint blk_size = 0; | 37 | uint blk_size = 0; |
38 | 38 | ||
39 | if (bcb_command == NULL) | 39 | if (bcb_command == NULL) |
40 | return -1; | 40 | return -1; |
41 | 41 | ||
42 | 42 | ||
43 | ret = bcb_rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); | 43 | ret = bcb_rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); |
44 | if (ret) { | 44 | if (ret) { |
45 | printf("write_bootctl, bcb_rw_block read failed\n"); | 45 | printf("write_bootctl, bcb_rw_block read failed\n"); |
46 | return -1; | 46 | return -1; |
47 | } | 47 | } |
48 | 48 | ||
49 | offset_in_block = MISC_COMMAND%blk_size; | 49 | offset_in_block = MISC_COMMAND%blk_size; |
50 | memcpy(p_block + offset_in_block, bcb_command, 32); | 50 | memcpy(p_block + offset_in_block, bcb_command, 32); |
51 | 51 | ||
52 | ret = bcb_rw_block(false, NULL, NULL, p_block, MISC_COMMAND, 32); | 52 | ret = bcb_rw_block(false, NULL, NULL, p_block, MISC_COMMAND, 32); |
53 | if (ret) { | 53 | if (ret) { |
54 | free(p_block); | 54 | free(p_block); |
55 | printf("write_bootctl, bcb_rw_block write failed\n"); | 55 | printf("write_bootctl, bcb_rw_block write failed\n"); |
56 | return -1; | 56 | return -1; |
57 | } | 57 | } |
58 | 58 | ||
59 | free(p_block); | 59 | free(p_block); |
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | |||
63 | #ifdef CONFIG_ANDROID_RECOVERY | ||
64 | int bcb_write_recovery_opt(char *opts) | ||
65 | { | ||
66 | int ret = 0; | ||
67 | char *p_block = NULL; | ||
68 | uint offset_in_block = 0; | ||
69 | uint blk_size = 0; | ||
70 | |||
71 | if (opts == NULL) | ||
72 | return -1; | ||
73 | |||
74 | |||
75 | ret = bcb_rw_block(true, &p_block, &blk_size, NULL, RECOVERY_OPTIONS, 32); | ||
76 | if (ret) { | ||
77 | printf("write_bootctl, bcb_rw_block read failed\n"); | ||
78 | return -1; | ||
79 | } | ||
80 | |||
81 | offset_in_block = RECOVERY_OPTIONS%blk_size; | ||
82 | memcpy(p_block + offset_in_block, opts, 32); | ||
83 | |||
84 | ret = bcb_rw_block(false, NULL, NULL, p_block, RECOVERY_OPTIONS, 32); | ||
85 | if (ret) { | ||
86 | free(p_block); | ||
87 | printf("write_bootctl, bcb_rw_block write failed\n"); | ||
88 | return -1; | ||
89 | } | ||
90 | |||
91 | free(p_block); | ||
92 | return 0; | ||
93 | } | ||
94 | #endif | ||
62 | 95 |
drivers/fastboot/fb_fsl/fb_fsl_command.c
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * Copyright 2019 NXP | 3 | * Copyright 2019 NXP |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <asm/mach-imx/sys_proto.h> | 6 | #include <asm/mach-imx/sys_proto.h> |
7 | #include <fb_fsl.h> | 7 | #include <fb_fsl.h> |
8 | #include <fastboot.h> | 8 | #include <fastboot.h> |
9 | #include <fastboot-internal.h> | 9 | #include <fastboot-internal.h> |
10 | #include <mmc.h> | 10 | #include <mmc.h> |
11 | #include <android_image.h> | 11 | #include <android_image.h> |
12 | #include <asm/bootm.h> | 12 | #include <asm/bootm.h> |
13 | #include <nand.h> | 13 | #include <nand.h> |
14 | #include <part.h> | 14 | #include <part.h> |
15 | #include <sparse_format.h> | 15 | #include <sparse_format.h> |
16 | #include <image-sparse.h> | 16 | #include <image-sparse.h> |
17 | #include <image.h> | 17 | #include <image.h> |
18 | #include <asm/mach-imx/boot_mode.h> | 18 | #include <asm/mach-imx/boot_mode.h> |
19 | #include <asm/arch/sys_proto.h> | 19 | #include <asm/arch/sys_proto.h> |
20 | #include <asm/setup.h> | 20 | #include <asm/setup.h> |
21 | #include <env.h> | 21 | #include <env.h> |
22 | #ifdef CONFIG_ANDROID_RECOVERY | 22 | #ifdef CONFIG_ANDROID_RECOVERY |
23 | #include <recovery.h> | 23 | #include <recovery.h> |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | #ifdef CONFIG_BCB_SUPPORT | 26 | #ifdef CONFIG_BCB_SUPPORT |
27 | #include "bcb.h" | 27 | #include "bcb.h" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #ifdef CONFIG_AVB_SUPPORT | 30 | #ifdef CONFIG_AVB_SUPPORT |
31 | #include <dt_table.h> | 31 | #include <dt_table.h> |
32 | #include <fsl_avb.h> | 32 | #include <fsl_avb.h> |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #ifdef CONFIG_ANDROID_THINGS_SUPPORT | 35 | #ifdef CONFIG_ANDROID_THINGS_SUPPORT |
36 | #include <asm-generic/gpio.h> | 36 | #include <asm-generic/gpio.h> |
37 | #include <asm/mach-imx/gpio.h> | 37 | #include <asm/mach-imx/gpio.h> |
38 | #include "../lib/avb/fsl/fsl_avbkey.h" | 38 | #include "../lib/avb/fsl/fsl_avbkey.h" |
39 | #include "../arch/arm/include/asm/mach-imx/hab.h" | 39 | #include "../arch/arm/include/asm/mach-imx/hab.h" |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #if defined(CONFIG_FASTBOOT_LOCK) | 42 | #if defined(CONFIG_FASTBOOT_LOCK) |
43 | #include "fastboot_lock_unlock.h" | 43 | #include "fastboot_lock_unlock.h" |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | #ifdef CONFIG_IMX_TRUSTY_OS | 46 | #ifdef CONFIG_IMX_TRUSTY_OS |
47 | #include "u-boot/sha256.h" | 47 | #include "u-boot/sha256.h" |
48 | #include <trusty/libtipc.h> | 48 | #include <trusty/libtipc.h> |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | #include "fb_fsl_common.h" | 51 | #include "fb_fsl_common.h" |
52 | 52 | ||
53 | #define EP_BUFFER_SIZE 4096 | 53 | #define EP_BUFFER_SIZE 4096 |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * fastboot_bytes_received - number of bytes received in the current download | 56 | * fastboot_bytes_received - number of bytes received in the current download |
57 | */ | 57 | */ |
58 | static u32 fastboot_bytes_received; | 58 | static u32 fastboot_bytes_received; |
59 | 59 | ||
60 | /** | 60 | /** |
61 | * fastboot_bytes_expected - number of bytes expected in the current download | 61 | * fastboot_bytes_expected - number of bytes expected in the current download |
62 | */ | 62 | */ |
63 | static u32 fastboot_bytes_expected; | 63 | static u32 fastboot_bytes_expected; |
64 | 64 | ||
65 | /* Write the bcb with fastboot bootloader commands */ | 65 | /* Write the bcb with fastboot bootloader commands */ |
66 | static void enable_fastboot_command(void) | 66 | static void enable_fastboot_command(void) |
67 | { | 67 | { |
68 | #ifdef CONFIG_BCB_SUPPORT | 68 | #ifdef CONFIG_BCB_SUPPORT |
69 | char fastboot_command[32] = {0}; | 69 | char fastboot_command[32] = {0}; |
70 | strncpy(fastboot_command, FASTBOOT_BCB_CMD, 31); | 70 | strncpy(fastboot_command, FASTBOOT_BCB_CMD, 31); |
71 | bcb_write_command(fastboot_command); | 71 | bcb_write_command(fastboot_command); |
72 | #endif | 72 | #endif |
73 | } | 73 | } |
74 | 74 | ||
75 | #ifdef CONFIG_ANDROID_RECOVERY | ||
76 | /* Write the recovery options with fastboot bootloader commands */ | ||
77 | static void enable_recovery_fastboot(void) | ||
78 | { | ||
79 | #ifdef CONFIG_BCB_SUPPORT | ||
80 | char msg[32] = {0}; | ||
81 | strncpy(msg, RECOVERY_BCB_CMD, 31); | ||
82 | bcb_write_command(msg); | ||
83 | strncpy(msg, RECOVERY_FASTBOOT_ARG, 31); | ||
84 | bcb_write_recovery_opt(msg); | ||
85 | #endif | ||
86 | } | ||
87 | #endif | ||
88 | |||
75 | /* Get the Boot mode from BCB cmd or Key pressed */ | 89 | /* Get the Boot mode from BCB cmd or Key pressed */ |
76 | static FbBootMode fastboot_get_bootmode(void) | 90 | static FbBootMode fastboot_get_bootmode(void) |
77 | { | 91 | { |
78 | int boot_mode = BOOTMODE_NORMAL; | 92 | int boot_mode = BOOTMODE_NORMAL; |
79 | #ifdef CONFIG_ANDROID_RECOVERY | 93 | #ifdef CONFIG_ANDROID_RECOVERY |
80 | if(is_recovery_key_pressing()) { | 94 | if(is_recovery_key_pressing()) { |
81 | boot_mode = BOOTMODE_RECOVERY_KEY_PRESSED; | 95 | boot_mode = BOOTMODE_RECOVERY_KEY_PRESSED; |
82 | return boot_mode; | 96 | return boot_mode; |
83 | } | 97 | } |
84 | #endif | 98 | #endif |
85 | #ifdef CONFIG_BCB_SUPPORT | 99 | #ifdef CONFIG_BCB_SUPPORT |
86 | int ret = 0; | 100 | int ret = 0; |
87 | char command[32]; | 101 | char command[32]; |
88 | ret = bcb_read_command(command); | 102 | ret = bcb_read_command(command); |
89 | if (ret < 0) { | 103 | if (ret < 0) { |
90 | printf("read command failed\n"); | 104 | printf("read command failed\n"); |
91 | return boot_mode; | 105 | return boot_mode; |
92 | } | 106 | } |
93 | if (!strcmp(command, FASTBOOT_BCB_CMD)) { | 107 | if (!strcmp(command, FASTBOOT_BCB_CMD)) { |
94 | boot_mode = BOOTMODE_FASTBOOT_BCB_CMD; | 108 | boot_mode = BOOTMODE_FASTBOOT_BCB_CMD; |
95 | } | 109 | } |
96 | #ifdef CONFIG_ANDROID_RECOVERY | 110 | #ifdef CONFIG_ANDROID_RECOVERY |
97 | else if (!strcmp(command, RECOVERY_BCB_CMD)) { | 111 | else if (!strcmp(command, RECOVERY_BCB_CMD)) { |
98 | boot_mode = BOOTMODE_RECOVERY_BCB_CMD; | 112 | boot_mode = BOOTMODE_RECOVERY_BCB_CMD; |
99 | } | 113 | } |
100 | #endif | 114 | #endif |
101 | 115 | ||
102 | /* Clean the mode once its read out, | 116 | /* Clean the mode once its read out, |
103 | no matter what in the mode string */ | 117 | no matter what in the mode string */ |
104 | memset(command, 0, 32); | 118 | memset(command, 0, 32); |
105 | bcb_write_command(command); | 119 | bcb_write_command(command); |
106 | #endif | 120 | #endif |
107 | return boot_mode; | 121 | return boot_mode; |
108 | } | 122 | } |
109 | 123 | ||
110 | /* export to lib_arm/board.c */ | 124 | /* export to lib_arm/board.c */ |
111 | void fastboot_run_bootmode(void) | 125 | void fastboot_run_bootmode(void) |
112 | { | 126 | { |
113 | FbBootMode boot_mode = fastboot_get_bootmode(); | 127 | FbBootMode boot_mode = fastboot_get_bootmode(); |
114 | switch(boot_mode){ | 128 | switch(boot_mode){ |
115 | case BOOTMODE_FASTBOOT_BCB_CMD: | 129 | case BOOTMODE_FASTBOOT_BCB_CMD: |
116 | /* Make the boot into fastboot mode*/ | 130 | /* Make the boot into fastboot mode*/ |
117 | puts("Fastboot: Got bootloader commands!\n"); | 131 | puts("Fastboot: Got bootloader commands!\n"); |
118 | run_command("fastboot 0", 0); | 132 | run_command("fastboot 0", 0); |
119 | break; | 133 | break; |
120 | #ifdef CONFIG_ANDROID_RECOVERY | 134 | #ifdef CONFIG_ANDROID_RECOVERY |
121 | case BOOTMODE_RECOVERY_BCB_CMD: | 135 | case BOOTMODE_RECOVERY_BCB_CMD: |
122 | case BOOTMODE_RECOVERY_KEY_PRESSED: | 136 | case BOOTMODE_RECOVERY_KEY_PRESSED: |
123 | /* Make the boot into recovery mode */ | 137 | /* Make the boot into recovery mode */ |
124 | puts("Fastboot: Got Recovery key pressing or recovery commands!\n"); | 138 | puts("Fastboot: Got Recovery key pressing or recovery commands!\n"); |
125 | board_recovery_setup(); | 139 | board_recovery_setup(); |
126 | break; | 140 | break; |
127 | #endif | 141 | #endif |
128 | default: | 142 | default: |
129 | /* skip special mode boot*/ | 143 | /* skip special mode boot*/ |
130 | puts("Fastboot: Normal\n"); | 144 | puts("Fastboot: Normal\n"); |
131 | break; | 145 | break; |
132 | } | 146 | } |
133 | } | 147 | } |
134 | 148 | ||
135 | 149 | ||
136 | 150 | ||
137 | /** | 151 | /** |
138 | * okay() - Send bare OKAY response | 152 | * okay() - Send bare OKAY response |
139 | * | 153 | * |
140 | * @cmd_parameter: Pointer to command parameter | 154 | * @cmd_parameter: Pointer to command parameter |
141 | * @response: Pointer to fastboot response buffer | 155 | * @response: Pointer to fastboot response buffer |
142 | * | 156 | * |
143 | * Send a bare OKAY fastboot response. This is used where the command is | 157 | * Send a bare OKAY fastboot response. This is used where the command is |
144 | * valid, but all the work is done after the response has been sent (e.g. | 158 | * valid, but all the work is done after the response has been sent (e.g. |
145 | * boot, reboot etc.) | 159 | * boot, reboot etc.) |
146 | */ | 160 | */ |
147 | static void okay(char *cmd_parameter, char *response) | 161 | static void okay(char *cmd_parameter, char *response) |
148 | { | 162 | { |
149 | fastboot_okay(NULL, response); | 163 | fastboot_okay(NULL, response); |
150 | } | 164 | } |
151 | 165 | ||
152 | /** | 166 | /** |
153 | * getvar() - Read a config/version variable | 167 | * getvar() - Read a config/version variable |
154 | * | 168 | * |
155 | * @cmd_parameter: Pointer to command parameter | 169 | * @cmd_parameter: Pointer to command parameter |
156 | * @response: Pointer to fastboot response buffer | 170 | * @response: Pointer to fastboot response buffer |
157 | */ | 171 | */ |
158 | static void getvar(char *cmd_parameter, char *response) | 172 | static void getvar(char *cmd_parameter, char *response) |
159 | { | 173 | { |
160 | fastboot_getvar(cmd_parameter, response); | 174 | fastboot_getvar(cmd_parameter, response); |
161 | } | 175 | } |
162 | 176 | ||
163 | /** | 177 | /** |
164 | * reboot_bootloader() - Sets reboot bootloader flag. | 178 | * reboot_bootloader() - Sets reboot bootloader flag. |
165 | * | 179 | * |
166 | * @cmd_parameter: Pointer to command parameter | 180 | * @cmd_parameter: Pointer to command parameter |
167 | * @response: Pointer to fastboot response buffer | 181 | * @response: Pointer to fastboot response buffer |
168 | */ | 182 | */ |
169 | static void reboot_bootloader(char *cmd_parameter, char *response) | 183 | static void reboot_bootloader(char *cmd_parameter, char *response) |
170 | { | 184 | { |
171 | enable_fastboot_command(); | 185 | enable_fastboot_command(); |
172 | 186 | ||
173 | if (fastboot_set_reboot_flag()) | 187 | if (fastboot_set_reboot_flag()) |
174 | fastboot_fail("Cannot set reboot flag", response); | 188 | fastboot_fail("Cannot set reboot flag", response); |
175 | else | 189 | else |
176 | fastboot_okay(NULL, response); | 190 | fastboot_okay(NULL, response); |
177 | } | 191 | } |
178 | 192 | ||
193 | #ifdef CONFIG_ANDROID_RECOVERY | ||
194 | /** | ||
195 | * reboot_fastboot() - Sets reboot fastboot flag. | ||
196 | * | ||
197 | * @cmd_parameter: Pointer to command parameter | ||
198 | * @response: Pointer to fastboot response buffer | ||
199 | */ | ||
200 | static void reboot_fastboot(char *cmd_parameter, char *response) | ||
201 | { | ||
202 | enable_recovery_fastboot(); | ||
203 | |||
204 | if (fastboot_set_reboot_flag()) | ||
205 | fastboot_fail("Cannot set reboot flag", response); | ||
206 | else | ||
207 | fastboot_okay(NULL, response); | ||
208 | } | ||
209 | #endif | ||
210 | |||
179 | static void upload(char *cmd_parameter, char *response) | 211 | static void upload(char *cmd_parameter, char *response) |
180 | { | 212 | { |
181 | if (!fastboot_bytes_received || fastboot_bytes_received > (EP_BUFFER_SIZE * 32)) { | 213 | if (!fastboot_bytes_received || fastboot_bytes_received > (EP_BUFFER_SIZE * 32)) { |
182 | fastboot_fail("", response); | 214 | fastboot_fail("", response); |
183 | return; | 215 | return; |
184 | } | 216 | } |
185 | 217 | ||
186 | printf("Will upload %d bytes.\n", fastboot_bytes_received); | 218 | printf("Will upload %d bytes.\n", fastboot_bytes_received); |
187 | snprintf(response, FASTBOOT_RESPONSE_LEN, "DATA%08x", fastboot_bytes_received); | 219 | snprintf(response, FASTBOOT_RESPONSE_LEN, "DATA%08x", fastboot_bytes_received); |
188 | fastboot_tx_write_more(response); | 220 | fastboot_tx_write_more(response); |
189 | 221 | ||
190 | fastboot_tx_write((const char *)(fastboot_buf_addr), fastboot_bytes_received); | 222 | fastboot_tx_write((const char *)(fastboot_buf_addr), fastboot_bytes_received); |
191 | 223 | ||
192 | snprintf(response,FASTBOOT_RESPONSE_LEN, "OKAY"); | 224 | snprintf(response,FASTBOOT_RESPONSE_LEN, "OKAY"); |
193 | fastboot_tx_write_more(response); | 225 | fastboot_tx_write_more(response); |
194 | 226 | ||
195 | fastboot_none_resp(response); | 227 | fastboot_none_resp(response); |
196 | } | 228 | } |
197 | 229 | ||
198 | /** | 230 | /** |
199 | * fastboot_download() - Start a download transfer from the client | 231 | * fastboot_download() - Start a download transfer from the client |
200 | * | 232 | * |
201 | * @cmd_parameter: Pointer to command parameter | 233 | * @cmd_parameter: Pointer to command parameter |
202 | * @response: Pointer to fastboot response buffer | 234 | * @response: Pointer to fastboot response buffer |
203 | */ | 235 | */ |
204 | static void download(char *cmd_parameter, char *response) | 236 | static void download(char *cmd_parameter, char *response) |
205 | { | 237 | { |
206 | char *tmp; | 238 | char *tmp; |
207 | 239 | ||
208 | if (!cmd_parameter) { | 240 | if (!cmd_parameter) { |
209 | fastboot_fail("Expected command parameter", response); | 241 | fastboot_fail("Expected command parameter", response); |
210 | return; | 242 | return; |
211 | } | 243 | } |
212 | fastboot_bytes_received = 0; | 244 | fastboot_bytes_received = 0; |
213 | fastboot_bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16); | 245 | fastboot_bytes_expected = simple_strtoul(cmd_parameter, &tmp, 16); |
214 | if (fastboot_bytes_expected == 0) { | 246 | if (fastboot_bytes_expected == 0) { |
215 | fastboot_fail("Expected nonzero image size", response); | 247 | fastboot_fail("Expected nonzero image size", response); |
216 | return; | 248 | return; |
217 | } | 249 | } |
218 | /* | 250 | /* |
219 | * Nothing to download yet. Response is of the form: | 251 | * Nothing to download yet. Response is of the form: |
220 | * [DATA|FAIL]$cmd_parameter | 252 | * [DATA|FAIL]$cmd_parameter |
221 | * | 253 | * |
222 | * where cmd_parameter is an 8 digit hexadecimal number | 254 | * where cmd_parameter is an 8 digit hexadecimal number |
223 | */ | 255 | */ |
224 | if (fastboot_bytes_expected > fastboot_buf_size) { | 256 | if (fastboot_bytes_expected > fastboot_buf_size) { |
225 | fastboot_fail(cmd_parameter, response); | 257 | fastboot_fail(cmd_parameter, response); |
226 | } else { | 258 | } else { |
227 | printf("Starting download of %d bytes\n", | 259 | printf("Starting download of %d bytes\n", |
228 | fastboot_bytes_expected); | 260 | fastboot_bytes_expected); |
229 | fastboot_response("DATA", response, "%s", cmd_parameter); | 261 | fastboot_response("DATA", response, "%s", cmd_parameter); |
230 | } | 262 | } |
231 | } | 263 | } |
232 | 264 | ||
233 | /** | 265 | /** |
234 | * fastboot_data_remaining() - return bytes remaining in current transfer | 266 | * fastboot_data_remaining() - return bytes remaining in current transfer |
235 | * | 267 | * |
236 | * Return: Number of bytes left in the current download | 268 | * Return: Number of bytes left in the current download |
237 | */ | 269 | */ |
238 | u32 fastboot_data_remaining(void) | 270 | u32 fastboot_data_remaining(void) |
239 | { | 271 | { |
240 | if (fastboot_bytes_received >= fastboot_bytes_expected) | 272 | if (fastboot_bytes_received >= fastboot_bytes_expected) |
241 | return 0; | 273 | return 0; |
242 | 274 | ||
243 | return fastboot_bytes_expected - fastboot_bytes_received; | 275 | return fastboot_bytes_expected - fastboot_bytes_received; |
244 | } | 276 | } |
245 | 277 | ||
246 | /** | 278 | /** |
247 | * fastboot_data_download() - Copy image data to fastboot_buf_addr. | 279 | * fastboot_data_download() - Copy image data to fastboot_buf_addr. |
248 | * | 280 | * |
249 | * @fastboot_data: Pointer to received fastboot data | 281 | * @fastboot_data: Pointer to received fastboot data |
250 | * @fastboot_data_len: Length of received fastboot data | 282 | * @fastboot_data_len: Length of received fastboot data |
251 | * @response: Pointer to fastboot response buffer | 283 | * @response: Pointer to fastboot response buffer |
252 | * | 284 | * |
253 | * Copies image data from fastboot_data to fastboot_buf_addr. Writes to | 285 | * Copies image data from fastboot_data to fastboot_buf_addr. Writes to |
254 | * response. fastboot_bytes_received is updated to indicate the number | 286 | * response. fastboot_bytes_received is updated to indicate the number |
255 | * of bytes that have been transferred. | 287 | * of bytes that have been transferred. |
256 | * | 288 | * |
257 | * On completion sets image_size and ${filesize} to the total size of the | 289 | * On completion sets image_size and ${filesize} to the total size of the |
258 | * downloaded image. | 290 | * downloaded image. |
259 | */ | 291 | */ |
260 | void fastboot_data_download(const void *fastboot_data, | 292 | void fastboot_data_download(const void *fastboot_data, |
261 | unsigned int fastboot_data_len, | 293 | unsigned int fastboot_data_len, |
262 | char *response) | 294 | char *response) |
263 | { | 295 | { |
264 | #define BYTES_PER_DOT 0x20000 | 296 | #define BYTES_PER_DOT 0x20000 |
265 | u32 pre_dot_num, now_dot_num; | 297 | u32 pre_dot_num, now_dot_num; |
266 | 298 | ||
267 | if (fastboot_data_len == 0 || | 299 | if (fastboot_data_len == 0 || |
268 | (fastboot_bytes_received + fastboot_data_len) > | 300 | (fastboot_bytes_received + fastboot_data_len) > |
269 | fastboot_bytes_expected) { | 301 | fastboot_bytes_expected) { |
270 | fastboot_fail("Received invalid data length", | 302 | fastboot_fail("Received invalid data length", |
271 | response); | 303 | response); |
272 | return; | 304 | return; |
273 | } | 305 | } |
274 | /* Download data to fastboot_buf_addr */ | 306 | /* Download data to fastboot_buf_addr */ |
275 | memcpy(fastboot_buf_addr + fastboot_bytes_received, | 307 | memcpy(fastboot_buf_addr + fastboot_bytes_received, |
276 | fastboot_data, fastboot_data_len); | 308 | fastboot_data, fastboot_data_len); |
277 | 309 | ||
278 | pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT; | 310 | pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT; |
279 | fastboot_bytes_received += fastboot_data_len; | 311 | fastboot_bytes_received += fastboot_data_len; |
280 | now_dot_num = fastboot_bytes_received / BYTES_PER_DOT; | 312 | now_dot_num = fastboot_bytes_received / BYTES_PER_DOT; |
281 | 313 | ||
282 | if (pre_dot_num != now_dot_num) { | 314 | if (pre_dot_num != now_dot_num) { |
283 | putc('.'); | 315 | putc('.'); |
284 | if (!(now_dot_num % 74)) | 316 | if (!(now_dot_num % 74)) |
285 | putc('\n'); | 317 | putc('\n'); |
286 | } | 318 | } |
287 | *response = '\0'; | 319 | *response = '\0'; |
288 | } | 320 | } |
289 | 321 | ||
290 | /** | 322 | /** |
291 | * fastboot_data_complete() - Mark current transfer complete | 323 | * fastboot_data_complete() - Mark current transfer complete |
292 | * | 324 | * |
293 | * @response: Pointer to fastboot response buffer | 325 | * @response: Pointer to fastboot response buffer |
294 | * | 326 | * |
295 | * Set image_size and ${filesize} to the total size of the downloaded image. | 327 | * Set image_size and ${filesize} to the total size of the downloaded image. |
296 | */ | 328 | */ |
297 | void fastboot_data_complete(char *response) | 329 | void fastboot_data_complete(char *response) |
298 | { | 330 | { |
299 | /* Download complete. Respond with "OKAY" */ | 331 | /* Download complete. Respond with "OKAY" */ |
300 | fastboot_okay(NULL, response); | 332 | fastboot_okay(NULL, response); |
301 | printf("\ndownloading of %d bytes finished\n", fastboot_bytes_received); | 333 | printf("\ndownloading of %d bytes finished\n", fastboot_bytes_received); |
302 | env_set_hex("filesize", fastboot_bytes_received); | 334 | env_set_hex("filesize", fastboot_bytes_received); |
303 | env_set_hex("fastboot_bytes", fastboot_bytes_received); | 335 | env_set_hex("fastboot_bytes", fastboot_bytes_received); |
304 | fastboot_bytes_expected = 0; | 336 | fastboot_bytes_expected = 0; |
305 | } | 337 | } |
306 | 338 | ||
307 | #if defined(CONFIG_FASTBOOT_LOCK) | 339 | #if defined(CONFIG_FASTBOOT_LOCK) |
308 | static int partition_table_valid(void) | 340 | static int partition_table_valid(void) |
309 | { | 341 | { |
310 | int status, mmc_no; | 342 | int status, mmc_no; |
311 | struct blk_desc *dev_desc; | 343 | struct blk_desc *dev_desc; |
312 | #if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_ARM64) | 344 | #if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_ARM64) |
313 | /* Prevent other partition accessing when no TOS flashed. */ | 345 | /* Prevent other partition accessing when no TOS flashed. */ |
314 | if (!tos_flashed) | 346 | if (!tos_flashed) |
315 | return 0; | 347 | return 0; |
316 | #endif | 348 | #endif |
317 | disk_partition_t info; | 349 | disk_partition_t info; |
318 | mmc_no = fastboot_devinfo.dev_id; | 350 | mmc_no = fastboot_devinfo.dev_id; |
319 | dev_desc = blk_get_dev("mmc", mmc_no); | 351 | dev_desc = blk_get_dev("mmc", mmc_no); |
320 | if (dev_desc) | 352 | if (dev_desc) |
321 | status = part_get_info(dev_desc, 1, &info); | 353 | status = part_get_info(dev_desc, 1, &info); |
322 | else | 354 | else |
323 | status = -1; | 355 | status = -1; |
324 | return (status == 0); | 356 | return (status == 0); |
325 | } | 357 | } |
326 | 358 | ||
327 | static void wipe_all_userdata(void) | 359 | static void wipe_all_userdata(void) |
328 | { | 360 | { |
329 | char response[FASTBOOT_RESPONSE_LEN]; | 361 | char response[FASTBOOT_RESPONSE_LEN]; |
330 | 362 | ||
331 | /* Erase all user data */ | 363 | /* Erase all user data */ |
332 | printf("Start userdata wipe process....\n"); | 364 | printf("Start userdata wipe process....\n"); |
333 | /* Erase /data partition */ | 365 | /* Erase /data partition */ |
334 | fastboot_wipe_data_partition(); | 366 | fastboot_wipe_data_partition(); |
335 | 367 | ||
336 | #if defined (CONFIG_ANDROID_SUPPORT) || defined (CONFIG_ANDROID_AUTO_SUPPORT) | 368 | #if defined (CONFIG_ANDROID_SUPPORT) || defined (CONFIG_ANDROID_AUTO_SUPPORT) |
337 | /* Erase the misc partition. */ | 369 | /* Erase the misc partition. */ |
338 | process_erase_mmc(FASTBOOT_PARTITION_MISC, response); | 370 | process_erase_mmc(FASTBOOT_PARTITION_MISC, response); |
339 | #endif | 371 | #endif |
340 | 372 | ||
341 | #ifndef CONFIG_ANDROID_AB_SUPPORT | 373 | #ifndef CONFIG_ANDROID_AB_SUPPORT |
342 | /* Erase the cache partition for legacy imx6/7 */ | 374 | /* Erase the cache partition for legacy imx6/7 */ |
343 | process_erase_mmc(FASTBOOT_PARTITION_CACHE, response); | 375 | process_erase_mmc(FASTBOOT_PARTITION_CACHE, response); |
344 | #endif | 376 | #endif |
345 | 377 | ||
346 | #if defined(AVB_RPMB) && !defined(CONFIG_IMX_TRUSTY_OS) | 378 | #if defined(AVB_RPMB) && !defined(CONFIG_IMX_TRUSTY_OS) |
347 | printf("Start stored_rollback_index wipe process....\n"); | 379 | printf("Start stored_rollback_index wipe process....\n"); |
348 | rbkidx_erase(); | 380 | rbkidx_erase(); |
349 | printf("Wipe stored_rollback_index completed.\n"); | 381 | printf("Wipe stored_rollback_index completed.\n"); |
350 | #endif | 382 | #endif |
351 | printf("Wipe userdata completed.\n"); | 383 | printf("Wipe userdata completed.\n"); |
352 | } | 384 | } |
353 | 385 | ||
354 | static FbLockState do_fastboot_unlock(bool force) | 386 | static FbLockState do_fastboot_unlock(bool force) |
355 | { | 387 | { |
356 | int status; | 388 | int status; |
357 | 389 | ||
358 | if (fastboot_get_lock_stat() == FASTBOOT_UNLOCK) { | 390 | if (fastboot_get_lock_stat() == FASTBOOT_UNLOCK) { |
359 | printf("The device is already unlocked\n"); | 391 | printf("The device is already unlocked\n"); |
360 | return FASTBOOT_UNLOCK; | 392 | return FASTBOOT_UNLOCK; |
361 | } | 393 | } |
362 | if ((fastboot_lock_enable() == FASTBOOT_UL_ENABLE) || force) { | 394 | if ((fastboot_lock_enable() == FASTBOOT_UL_ENABLE) || force) { |
363 | printf("It is able to unlock device. %d\n",fastboot_lock_enable()); | 395 | printf("It is able to unlock device. %d\n",fastboot_lock_enable()); |
364 | 396 | ||
365 | #if defined(CONFIG_SECURE_UNLOCK) && defined(CONFIG_IMX_TRUSTY_OS) | 397 | #if defined(CONFIG_SECURE_UNLOCK) && defined(CONFIG_IMX_TRUSTY_OS) |
366 | if ((fastboot_bytes_received == 0) || !hab_is_enabled()) { | 398 | if ((fastboot_bytes_received == 0) || !hab_is_enabled()) { |
367 | printf("No unlock credential found or hab is not closed!\n"); | 399 | printf("No unlock credential found or hab is not closed!\n"); |
368 | return FASTBOOT_LOCK_ERROR; | 400 | return FASTBOOT_LOCK_ERROR; |
369 | } else { | 401 | } else { |
370 | char *serial = get_serial(); | 402 | char *serial = get_serial(); |
371 | status = trusty_verify_secure_unlock(fastboot_buf_addr, | 403 | status = trusty_verify_secure_unlock(fastboot_buf_addr, |
372 | fastboot_bytes_received, | 404 | fastboot_bytes_received, |
373 | serial, 16); | 405 | serial, 16); |
374 | if (status < 0) { | 406 | if (status < 0) { |
375 | printf("verify secure unlock credential fail due Trusty return %d\n", status); | 407 | printf("verify secure unlock credential fail due Trusty return %d\n", status); |
376 | return FASTBOOT_LOCK_ERROR; | 408 | return FASTBOOT_LOCK_ERROR; |
377 | } | 409 | } |
378 | } | 410 | } |
379 | #endif | 411 | #endif |
380 | wipe_all_userdata(); | 412 | wipe_all_userdata(); |
381 | status = fastboot_set_lock_stat(FASTBOOT_UNLOCK); | 413 | status = fastboot_set_lock_stat(FASTBOOT_UNLOCK); |
382 | if (status < 0) | 414 | if (status < 0) |
383 | return FASTBOOT_LOCK_ERROR; | 415 | return FASTBOOT_LOCK_ERROR; |
384 | } else { | 416 | } else { |
385 | printf("It is not able to unlock device."); | 417 | printf("It is not able to unlock device."); |
386 | return FASTBOOT_LOCK_ERROR; | 418 | return FASTBOOT_LOCK_ERROR; |
387 | } | 419 | } |
388 | 420 | ||
389 | return FASTBOOT_UNLOCK; | 421 | return FASTBOOT_UNLOCK; |
390 | } | 422 | } |
391 | 423 | ||
392 | static FbLockState do_fastboot_lock(void) | 424 | static FbLockState do_fastboot_lock(void) |
393 | { | 425 | { |
394 | int status; | 426 | int status; |
395 | 427 | ||
396 | if (fastboot_get_lock_stat() == FASTBOOT_LOCK) { | 428 | if (fastboot_get_lock_stat() == FASTBOOT_LOCK) { |
397 | printf("The device is already locked\n"); | 429 | printf("The device is already locked\n"); |
398 | return FASTBOOT_LOCK; | 430 | return FASTBOOT_LOCK; |
399 | } | 431 | } |
400 | 432 | ||
401 | wipe_all_userdata(); | 433 | wipe_all_userdata(); |
402 | status = fastboot_set_lock_stat(FASTBOOT_LOCK); | 434 | status = fastboot_set_lock_stat(FASTBOOT_LOCK); |
403 | if (status < 0) | 435 | if (status < 0) |
404 | return FASTBOOT_LOCK_ERROR; | 436 | return FASTBOOT_LOCK_ERROR; |
405 | 437 | ||
406 | return FASTBOOT_LOCK; | 438 | return FASTBOOT_LOCK; |
407 | } | 439 | } |
408 | 440 | ||
409 | static bool endswith(char* s, char* subs) { | 441 | static bool endswith(char* s, char* subs) { |
410 | if (!s || !subs) | 442 | if (!s || !subs) |
411 | return false; | 443 | return false; |
412 | uint32_t len = strlen(s); | 444 | uint32_t len = strlen(s); |
413 | uint32_t sublen = strlen(subs); | 445 | uint32_t sublen = strlen(subs); |
414 | if (len < sublen) { | 446 | if (len < sublen) { |
415 | return false; | 447 | return false; |
416 | } | 448 | } |
417 | if (strncmp(s + len - sublen, subs, sublen)) { | 449 | if (strncmp(s + len - sublen, subs, sublen)) { |
418 | return false; | 450 | return false; |
419 | } | 451 | } |
420 | return true; | 452 | return true; |
421 | } | 453 | } |
422 | 454 | ||
423 | static void flashing(char *cmd, char *response) | 455 | static void flashing(char *cmd, char *response) |
424 | { | 456 | { |
425 | FbLockState status; | 457 | FbLockState status; |
426 | FbLockEnableResult result; | 458 | FbLockEnableResult result; |
427 | if (endswith(cmd, "lock_critical")) { | 459 | if (endswith(cmd, "lock_critical")) { |
428 | strcpy(response, "OKAY"); | 460 | strcpy(response, "OKAY"); |
429 | } | 461 | } |
430 | #ifdef CONFIG_AVB_ATX | 462 | #ifdef CONFIG_AVB_ATX |
431 | else if (endswith(cmd, FASTBOOT_AVB_AT_PERM_ATTR)) { | 463 | else if (endswith(cmd, FASTBOOT_AVB_AT_PERM_ATTR)) { |
432 | if (avb_atx_fuse_perm_attr(fastboot_buf_addr, fastboot_bytes_received)) | 464 | if (avb_atx_fuse_perm_attr(fastboot_buf_addr, fastboot_bytes_received)) |
433 | strcpy(response, "FAILInternal error!"); | 465 | strcpy(response, "FAILInternal error!"); |
434 | else | 466 | else |
435 | strcpy(response, "OKAY"); | 467 | strcpy(response, "OKAY"); |
436 | } else if (endswith(cmd, FASTBOOT_AT_GET_UNLOCK_CHALLENGE)) { | 468 | } else if (endswith(cmd, FASTBOOT_AT_GET_UNLOCK_CHALLENGE)) { |
437 | if (avb_atx_get_unlock_challenge(fsl_avb_ops.atx_ops, | 469 | if (avb_atx_get_unlock_challenge(fsl_avb_ops.atx_ops, |
438 | fastboot_buf_addr, &fastboot_bytes_received)) | 470 | fastboot_buf_addr, &fastboot_bytes_received)) |
439 | strcpy(response, "FAILInternal error!"); | 471 | strcpy(response, "FAILInternal error!"); |
440 | else | 472 | else |
441 | strcpy(response, "OKAY"); | 473 | strcpy(response, "OKAY"); |
442 | } else if (endswith(cmd, FASTBOOT_AT_UNLOCK_VBOOT)) { | 474 | } else if (endswith(cmd, FASTBOOT_AT_UNLOCK_VBOOT)) { |
443 | if (at_unlock_vboot_is_disabled()) { | 475 | if (at_unlock_vboot_is_disabled()) { |
444 | printf("unlock vboot already disabled, can't unlock the device!\n"); | 476 | printf("unlock vboot already disabled, can't unlock the device!\n"); |
445 | strcpy(response, "FAILunlock vboot already disabled!."); | 477 | strcpy(response, "FAILunlock vboot already disabled!."); |
446 | } else { | 478 | } else { |
447 | #ifdef CONFIG_AT_AUTHENTICATE_UNLOCK | 479 | #ifdef CONFIG_AT_AUTHENTICATE_UNLOCK |
448 | if (avb_atx_verify_unlock_credential(fsl_avb_ops.atx_ops, | 480 | if (avb_atx_verify_unlock_credential(fsl_avb_ops.atx_ops, |
449 | fastboot_buf_addr)) | 481 | fastboot_buf_addr)) |
450 | strcpy(response, "FAILIncorrect unlock credential!"); | 482 | strcpy(response, "FAILIncorrect unlock credential!"); |
451 | else { | 483 | else { |
452 | #endif | 484 | #endif |
453 | status = do_fastboot_unlock(true); | 485 | status = do_fastboot_unlock(true); |
454 | if (status != FASTBOOT_LOCK_ERROR) | 486 | if (status != FASTBOOT_LOCK_ERROR) |
455 | strcpy(response, "OKAY"); | 487 | strcpy(response, "OKAY"); |
456 | else | 488 | else |
457 | strcpy(response, "FAILunlock device failed."); | 489 | strcpy(response, "FAILunlock device failed."); |
458 | #ifdef CONFIG_AT_AUTHENTICATE_UNLOCK | 490 | #ifdef CONFIG_AT_AUTHENTICATE_UNLOCK |
459 | } | 491 | } |
460 | #endif | 492 | #endif |
461 | } | 493 | } |
462 | } else if (endswith(cmd, FASTBOOT_AT_LOCK_VBOOT)) { | 494 | } else if (endswith(cmd, FASTBOOT_AT_LOCK_VBOOT)) { |
463 | if (perm_attr_are_fused()) { | 495 | if (perm_attr_are_fused()) { |
464 | status = do_fastboot_lock(); | 496 | status = do_fastboot_lock(); |
465 | if (status != FASTBOOT_LOCK_ERROR) | 497 | if (status != FASTBOOT_LOCK_ERROR) |
466 | strcpy(response, "OKAY"); | 498 | strcpy(response, "OKAY"); |
467 | else | 499 | else |
468 | strcpy(response, "FAILlock device failed."); | 500 | strcpy(response, "FAILlock device failed."); |
469 | } else | 501 | } else |
470 | strcpy(response, "FAILpermanent attributes not fused!"); | 502 | strcpy(response, "FAILpermanent attributes not fused!"); |
471 | } else if (endswith(cmd, FASTBOOT_AT_DISABLE_UNLOCK_VBOOT)) { | 503 | } else if (endswith(cmd, FASTBOOT_AT_DISABLE_UNLOCK_VBOOT)) { |
472 | /* This command can only be called after 'oem at-lock-vboot' */ | 504 | /* This command can only be called after 'oem at-lock-vboot' */ |
473 | status = fastboot_get_lock_stat(); | 505 | status = fastboot_get_lock_stat(); |
474 | if (status == FASTBOOT_LOCK) { | 506 | if (status == FASTBOOT_LOCK) { |
475 | if (at_unlock_vboot_is_disabled()) { | 507 | if (at_unlock_vboot_is_disabled()) { |
476 | printf("unlock vboot already disabled!\n"); | 508 | printf("unlock vboot already disabled!\n"); |
477 | strcpy(response, "OKAY"); | 509 | strcpy(response, "OKAY"); |
478 | } | 510 | } |
479 | else { | 511 | else { |
480 | if (!at_disable_vboot_unlock()) | 512 | if (!at_disable_vboot_unlock()) |
481 | strcpy(response, "OKAY"); | 513 | strcpy(response, "OKAY"); |
482 | else | 514 | else |
483 | strcpy(response, "FAILdisable unlock vboot fail!"); | 515 | strcpy(response, "FAILdisable unlock vboot fail!"); |
484 | } | 516 | } |
485 | } else | 517 | } else |
486 | strcpy(response, "FAILplease lock the device first!"); | 518 | strcpy(response, "FAILplease lock the device first!"); |
487 | } | 519 | } |
488 | #endif /* CONFIG_AVB_ATX */ | 520 | #endif /* CONFIG_AVB_ATX */ |
489 | #ifdef CONFIG_ANDROID_THINGS_SUPPORT | 521 | #ifdef CONFIG_ANDROID_THINGS_SUPPORT |
490 | else if (endswith(cmd, FASTBOOT_BOOTLOADER_VBOOT_KEY)) { | 522 | else if (endswith(cmd, FASTBOOT_BOOTLOADER_VBOOT_KEY)) { |
491 | strcpy(response, "OKAY"); | 523 | strcpy(response, "OKAY"); |
492 | } | 524 | } |
493 | #endif /* CONFIG_ANDROID_THINGS_SUPPORT */ | 525 | #endif /* CONFIG_ANDROID_THINGS_SUPPORT */ |
494 | #ifdef CONFIG_IMX_TRUSTY_OS | 526 | #ifdef CONFIG_IMX_TRUSTY_OS |
495 | else if (endswith(cmd, FASTBOOT_GET_CA_REQ)) { | 527 | else if (endswith(cmd, FASTBOOT_GET_CA_REQ)) { |
496 | uint8_t *ca_output; | 528 | uint8_t *ca_output; |
497 | uint32_t ca_length, cp_length; | 529 | uint32_t ca_length, cp_length; |
498 | if (trusty_atap_get_ca_request(fastboot_buf_addr, fastboot_bytes_received, | 530 | if (trusty_atap_get_ca_request(fastboot_buf_addr, fastboot_bytes_received, |
499 | &(ca_output), &ca_length)) { | 531 | &(ca_output), &ca_length)) { |
500 | printf("ERROR get_ca_request failed!\n"); | 532 | printf("ERROR get_ca_request failed!\n"); |
501 | strcpy(response, "FAILInternal error!"); | 533 | strcpy(response, "FAILInternal error!"); |
502 | } else { | 534 | } else { |
503 | cp_length = min((uint32_t)CONFIG_FASTBOOT_BUF_SIZE, ca_length); | 535 | cp_length = min((uint32_t)CONFIG_FASTBOOT_BUF_SIZE, ca_length); |
504 | memcpy(fastboot_buf_addr, ca_output, cp_length); | 536 | memcpy(fastboot_buf_addr, ca_output, cp_length); |
505 | fastboot_bytes_received = ca_length; | 537 | fastboot_bytes_received = ca_length; |
506 | strcpy(response, "OKAY"); | 538 | strcpy(response, "OKAY"); |
507 | } | 539 | } |
508 | 540 | ||
509 | } else if (endswith(cmd, FASTBOOT_SET_CA_RESP)) { | 541 | } else if (endswith(cmd, FASTBOOT_SET_CA_RESP)) { |
510 | if (trusty_atap_set_ca_response(fastboot_buf_addr, fastboot_bytes_received)) { | 542 | if (trusty_atap_set_ca_response(fastboot_buf_addr, fastboot_bytes_received)) { |
511 | printf("ERROR set_ca_response failed!\n"); | 543 | printf("ERROR set_ca_response failed!\n"); |
512 | strcpy(response, "FAILInternal error!"); | 544 | strcpy(response, "FAILInternal error!"); |
513 | } else | 545 | } else |
514 | strcpy(response, "OKAY"); | 546 | strcpy(response, "OKAY"); |
515 | } else if (endswith(cmd, FASTBOOT_SET_RSA_ATTESTATION_KEY_ENC)) { | 547 | } else if (endswith(cmd, FASTBOOT_SET_RSA_ATTESTATION_KEY_ENC)) { |
516 | if (trusty_set_attestation_key_enc(fastboot_buf_addr, | 548 | if (trusty_set_attestation_key_enc(fastboot_buf_addr, |
517 | fastboot_bytes_received, | 549 | fastboot_bytes_received, |
518 | KM_ALGORITHM_RSA)) { | 550 | KM_ALGORITHM_RSA)) { |
519 | printf("ERROR set rsa attestation key failed!\n"); | 551 | printf("ERROR set rsa attestation key failed!\n"); |
520 | strcpy(response, "FAILInternal error!"); | 552 | strcpy(response, "FAILInternal error!"); |
521 | } else { | 553 | } else { |
522 | printf("Set rsa attestation key successfully!\n"); | 554 | printf("Set rsa attestation key successfully!\n"); |
523 | strcpy(response, "OKAY"); | 555 | strcpy(response, "OKAY"); |
524 | } | 556 | } |
525 | } else if (endswith(cmd, FASTBOOT_SET_EC_ATTESTATION_KEY_ENC)) { | 557 | } else if (endswith(cmd, FASTBOOT_SET_EC_ATTESTATION_KEY_ENC)) { |
526 | if (trusty_set_attestation_key_enc(fastboot_buf_addr, | 558 | if (trusty_set_attestation_key_enc(fastboot_buf_addr, |
527 | fastboot_bytes_received, | 559 | fastboot_bytes_received, |
528 | KM_ALGORITHM_EC)) { | 560 | KM_ALGORITHM_EC)) { |
529 | printf("ERROR set ec attestation key failed!\n"); | 561 | printf("ERROR set ec attestation key failed!\n"); |
530 | strcpy(response, "FAILInternal error!"); | 562 | strcpy(response, "FAILInternal error!"); |
531 | } else { | 563 | } else { |
532 | printf("Set ec attestation key successfully!\n"); | 564 | printf("Set ec attestation key successfully!\n"); |
533 | strcpy(response, "OKAY"); | 565 | strcpy(response, "OKAY"); |
534 | } | 566 | } |
535 | } else if (endswith(cmd, FASTBOOT_APPEND_RSA_ATTESTATION_CERT_ENC)) { | 567 | } else if (endswith(cmd, FASTBOOT_APPEND_RSA_ATTESTATION_CERT_ENC)) { |
536 | if (trusty_append_attestation_cert_chain_enc(fastboot_buf_addr, | 568 | if (trusty_append_attestation_cert_chain_enc(fastboot_buf_addr, |
537 | fastboot_bytes_received, | 569 | fastboot_bytes_received, |
538 | KM_ALGORITHM_RSA)) { | 570 | KM_ALGORITHM_RSA)) { |
539 | printf("ERROR append rsa attestation cert chain failed!\n"); | 571 | printf("ERROR append rsa attestation cert chain failed!\n"); |
540 | strcpy(response, "FAILInternal error!"); | 572 | strcpy(response, "FAILInternal error!"); |
541 | } else { | 573 | } else { |
542 | printf("Append rsa attestation key successfully!\n"); | 574 | printf("Append rsa attestation key successfully!\n"); |
543 | strcpy(response, "OKAY"); | 575 | strcpy(response, "OKAY"); |
544 | } | 576 | } |
545 | } else if (endswith(cmd, FASTBOOT_APPEND_EC_ATTESTATION_CERT_ENC)) { | 577 | } else if (endswith(cmd, FASTBOOT_APPEND_EC_ATTESTATION_CERT_ENC)) { |
546 | if (trusty_append_attestation_cert_chain_enc(fastboot_buf_addr, | 578 | if (trusty_append_attestation_cert_chain_enc(fastboot_buf_addr, |
547 | fastboot_bytes_received, | 579 | fastboot_bytes_received, |
548 | KM_ALGORITHM_EC)) { | 580 | KM_ALGORITHM_EC)) { |
549 | printf("ERROR append ec attestation cert chain failed!\n"); | 581 | printf("ERROR append ec attestation cert chain failed!\n"); |
550 | strcpy(response, "FAILInternal error!"); | 582 | strcpy(response, "FAILInternal error!"); |
551 | } else { | 583 | } else { |
552 | printf("Append ec attestation key successfully!\n"); | 584 | printf("Append ec attestation key successfully!\n"); |
553 | strcpy(response, "OKAY"); | 585 | strcpy(response, "OKAY"); |
554 | } | 586 | } |
555 | } else if (endswith(cmd, FASTBOOT_SET_RSA_ATTESTATION_KEY)) { | 587 | } else if (endswith(cmd, FASTBOOT_SET_RSA_ATTESTATION_KEY)) { |
556 | if (trusty_set_attestation_key(fastboot_buf_addr, | 588 | if (trusty_set_attestation_key(fastboot_buf_addr, |
557 | fastboot_bytes_received, | 589 | fastboot_bytes_received, |
558 | KM_ALGORITHM_RSA)) { | 590 | KM_ALGORITHM_RSA)) { |
559 | printf("ERROR set rsa attestation key failed!\n"); | 591 | printf("ERROR set rsa attestation key failed!\n"); |
560 | strcpy(response, "FAILInternal error!"); | 592 | strcpy(response, "FAILInternal error!"); |
561 | } else { | 593 | } else { |
562 | printf("Set rsa attestation key successfully!\n"); | 594 | printf("Set rsa attestation key successfully!\n"); |
563 | strcpy(response, "OKAY"); | 595 | strcpy(response, "OKAY"); |
564 | } | 596 | } |
565 | } else if (endswith(cmd, FASTBOOT_SET_EC_ATTESTATION_KEY)) { | 597 | } else if (endswith(cmd, FASTBOOT_SET_EC_ATTESTATION_KEY)) { |
566 | if (trusty_set_attestation_key(fastboot_buf_addr, | 598 | if (trusty_set_attestation_key(fastboot_buf_addr, |
567 | fastboot_bytes_received, | 599 | fastboot_bytes_received, |
568 | KM_ALGORITHM_EC)) { | 600 | KM_ALGORITHM_EC)) { |
569 | printf("ERROR set ec attestation key failed!\n"); | 601 | printf("ERROR set ec attestation key failed!\n"); |
570 | strcpy(response, "FAILInternal error!"); | 602 | strcpy(response, "FAILInternal error!"); |
571 | } else { | 603 | } else { |
572 | printf("Set ec attestation key successfully!\n"); | 604 | printf("Set ec attestation key successfully!\n"); |
573 | strcpy(response, "OKAY"); | 605 | strcpy(response, "OKAY"); |
574 | } | 606 | } |
575 | } else if (endswith(cmd, FASTBOOT_APPEND_RSA_ATTESTATION_CERT)) { | 607 | } else if (endswith(cmd, FASTBOOT_APPEND_RSA_ATTESTATION_CERT)) { |
576 | if (trusty_append_attestation_cert_chain(fastboot_buf_addr, | 608 | if (trusty_append_attestation_cert_chain(fastboot_buf_addr, |
577 | fastboot_bytes_received, | 609 | fastboot_bytes_received, |
578 | KM_ALGORITHM_RSA)) { | 610 | KM_ALGORITHM_RSA)) { |
579 | printf("ERROR append rsa attestation cert chain failed!\n"); | 611 | printf("ERROR append rsa attestation cert chain failed!\n"); |
580 | strcpy(response, "FAILInternal error!"); | 612 | strcpy(response, "FAILInternal error!"); |
581 | } else { | 613 | } else { |
582 | printf("Append rsa attestation key successfully!\n"); | 614 | printf("Append rsa attestation key successfully!\n"); |
583 | strcpy(response, "OKAY"); | 615 | strcpy(response, "OKAY"); |
584 | } | 616 | } |
585 | } else if (endswith(cmd, FASTBOOT_APPEND_EC_ATTESTATION_CERT)) { | 617 | } else if (endswith(cmd, FASTBOOT_APPEND_EC_ATTESTATION_CERT)) { |
586 | if (trusty_append_attestation_cert_chain(fastboot_buf_addr, | 618 | if (trusty_append_attestation_cert_chain(fastboot_buf_addr, |
587 | fastboot_bytes_received, | 619 | fastboot_bytes_received, |
588 | KM_ALGORITHM_EC)) { | 620 | KM_ALGORITHM_EC)) { |
589 | printf("ERROR append ec attestation cert chain failed!\n"); | 621 | printf("ERROR append ec attestation cert chain failed!\n"); |
590 | strcpy(response, "FAILInternal error!"); | 622 | strcpy(response, "FAILInternal error!"); |
591 | } else { | 623 | } else { |
592 | printf("Append ec attestation key successfully!\n"); | 624 | printf("Append ec attestation key successfully!\n"); |
593 | strcpy(response, "OKAY"); | 625 | strcpy(response, "OKAY"); |
594 | } | 626 | } |
595 | } else if (endswith(cmd, FASTBOOT_GET_MPPUBK)) { | 627 | } else if (endswith(cmd, FASTBOOT_GET_MPPUBK)) { |
596 | if (fastboot_get_mppubk(fastboot_buf_addr, &fastboot_bytes_received)) { | 628 | if (fastboot_get_mppubk(fastboot_buf_addr, &fastboot_bytes_received)) { |
597 | printf("ERROR Generate mppubk failed!\n"); | 629 | printf("ERROR Generate mppubk failed!\n"); |
598 | strcpy(response, "FAILGenerate mppubk failed!"); | 630 | strcpy(response, "FAILGenerate mppubk failed!"); |
599 | } else { | 631 | } else { |
600 | printf("mppubk generated!\n"); | 632 | printf("mppubk generated!\n"); |
601 | strcpy(response, "OKAY"); | 633 | strcpy(response, "OKAY"); |
602 | } | 634 | } |
603 | } else if (endswith(cmd, FASTBOOT_GET_SERIAL_NUMBER)) { | 635 | } else if (endswith(cmd, FASTBOOT_GET_SERIAL_NUMBER)) { |
604 | char *serial = get_serial(); | 636 | char *serial = get_serial(); |
605 | 637 | ||
606 | if (!serial) | 638 | if (!serial) |
607 | strcpy(response, "FAILSerial number not support!"); | 639 | strcpy(response, "FAILSerial number not support!"); |
608 | else { | 640 | else { |
609 | /* Serial number will not exceed 16 bytes.*/ | 641 | /* Serial number will not exceed 16 bytes.*/ |
610 | strncpy(fastboot_buf_addr, serial, 16); | 642 | strncpy(fastboot_buf_addr, serial, 16); |
611 | fastboot_bytes_received = 16; | 643 | fastboot_bytes_received = 16; |
612 | printf("Serial number generated!\n"); | 644 | printf("Serial number generated!\n"); |
613 | strcpy(response, "OKAY"); | 645 | strcpy(response, "OKAY"); |
614 | } | 646 | } |
615 | } | 647 | } |
616 | #ifndef CONFIG_AVB_ATX | 648 | #ifndef CONFIG_AVB_ATX |
617 | else if (endswith(cmd, FASTBOOT_SET_RPMB_KEY)) { | 649 | else if (endswith(cmd, FASTBOOT_SET_RPMB_KEY)) { |
618 | if (fastboot_set_rpmb_key(fastboot_buf_addr, fastboot_bytes_received)) { | 650 | if (fastboot_set_rpmb_key(fastboot_buf_addr, fastboot_bytes_received)) { |
619 | printf("ERROR set rpmb key failed!\n"); | 651 | printf("ERROR set rpmb key failed!\n"); |
620 | strcpy(response, "FAILset rpmb key failed!"); | 652 | strcpy(response, "FAILset rpmb key failed!"); |
621 | } else | 653 | } else |
622 | strcpy(response, "OKAY"); | 654 | strcpy(response, "OKAY"); |
623 | } else if (endswith(cmd, FASTBOOT_SET_RPMB_RANDOM_KEY)) { | 655 | } else if (endswith(cmd, FASTBOOT_SET_RPMB_RANDOM_KEY)) { |
624 | if (fastboot_set_rpmb_random_key()) { | 656 | if (fastboot_set_rpmb_random_key()) { |
625 | printf("ERROR set rpmb random key failed!\n"); | 657 | printf("ERROR set rpmb random key failed!\n"); |
626 | strcpy(response, "FAILset rpmb random key failed!"); | 658 | strcpy(response, "FAILset rpmb random key failed!"); |
627 | } else | 659 | } else |
628 | strcpy(response, "OKAY"); | 660 | strcpy(response, "OKAY"); |
629 | } else if (endswith(cmd, FASTBOOT_SET_VBMETA_PUBLIC_KEY)) { | 661 | } else if (endswith(cmd, FASTBOOT_SET_VBMETA_PUBLIC_KEY)) { |
630 | if (avb_set_public_key(fastboot_buf_addr, | 662 | if (avb_set_public_key(fastboot_buf_addr, |
631 | fastboot_bytes_received)) | 663 | fastboot_bytes_received)) |
632 | strcpy(response, "FAILcan't set public key!"); | 664 | strcpy(response, "FAILcan't set public key!"); |
633 | else | 665 | else |
634 | strcpy(response, "OKAY"); | 666 | strcpy(response, "OKAY"); |
635 | } | 667 | } |
636 | #endif /* !CONFIG_AVB_ATX */ | 668 | #endif /* !CONFIG_AVB_ATX */ |
637 | #endif /* CONFIG_IMX_TRUSTY_OS */ | 669 | #endif /* CONFIG_IMX_TRUSTY_OS */ |
638 | else if (endswith(cmd, "unlock_critical")) { | 670 | else if (endswith(cmd, "unlock_critical")) { |
639 | strcpy(response, "OKAY"); | 671 | strcpy(response, "OKAY"); |
640 | } else if (endswith(cmd, "unlock")) { | 672 | } else if (endswith(cmd, "unlock")) { |
641 | printf("flashing unlock.\n"); | 673 | printf("flashing unlock.\n"); |
642 | #ifdef CONFIG_AVB_ATX | 674 | #ifdef CONFIG_AVB_ATX |
643 | /* We should do nothing here For Android Things which | 675 | /* We should do nothing here For Android Things which |
644 | * enables the authenticated unlock feature. | 676 | * enables the authenticated unlock feature. |
645 | */ | 677 | */ |
646 | strcpy(response, "OKAY"); | 678 | strcpy(response, "OKAY"); |
647 | #else | 679 | #else |
648 | status = do_fastboot_unlock(false); | 680 | status = do_fastboot_unlock(false); |
649 | if (status != FASTBOOT_LOCK_ERROR) | 681 | if (status != FASTBOOT_LOCK_ERROR) |
650 | strcpy(response, "OKAY"); | 682 | strcpy(response, "OKAY"); |
651 | else | 683 | else |
652 | strcpy(response, "FAILunlock device failed."); | 684 | strcpy(response, "FAILunlock device failed."); |
653 | #endif | 685 | #endif |
654 | } else if (endswith(cmd, "lock")) { | 686 | } else if (endswith(cmd, "lock")) { |
655 | #ifdef CONFIG_AVB_ATX | 687 | #ifdef CONFIG_AVB_ATX |
656 | /* We should do nothing here For Android Things which | 688 | /* We should do nothing here For Android Things which |
657 | * enables the at-lock-vboot feature. | 689 | * enables the at-lock-vboot feature. |
658 | */ | 690 | */ |
659 | strcpy(response, "OKAY"); | 691 | strcpy(response, "OKAY"); |
660 | #else | 692 | #else |
661 | printf("flashing lock.\n"); | 693 | printf("flashing lock.\n"); |
662 | status = do_fastboot_lock(); | 694 | status = do_fastboot_lock(); |
663 | if (status != FASTBOOT_LOCK_ERROR) | 695 | if (status != FASTBOOT_LOCK_ERROR) |
664 | strcpy(response, "OKAY"); | 696 | strcpy(response, "OKAY"); |
665 | else | 697 | else |
666 | strcpy(response, "FAILlock device failed."); | 698 | strcpy(response, "FAILlock device failed."); |
667 | #endif | 699 | #endif |
668 | } else if (endswith(cmd, "get_unlock_ability")) { | 700 | } else if (endswith(cmd, "get_unlock_ability")) { |
669 | result = fastboot_lock_enable(); | 701 | result = fastboot_lock_enable(); |
670 | if (result == FASTBOOT_UL_ENABLE) { | 702 | if (result == FASTBOOT_UL_ENABLE) { |
671 | fastboot_tx_write_more("INFO1"); | 703 | fastboot_tx_write_more("INFO1"); |
672 | strcpy(response, "OKAY"); | 704 | strcpy(response, "OKAY"); |
673 | } else if (result == FASTBOOT_UL_DISABLE) { | 705 | } else if (result == FASTBOOT_UL_DISABLE) { |
674 | fastboot_tx_write_more("INFO0"); | 706 | fastboot_tx_write_more("INFO0"); |
675 | strcpy(response, "OKAY"); | 707 | strcpy(response, "OKAY"); |
676 | } else { | 708 | } else { |
677 | printf("flashing get_unlock_ability fail!\n"); | 709 | printf("flashing get_unlock_ability fail!\n"); |
678 | strcpy(response, "FAILget unlock ability failed."); | 710 | strcpy(response, "FAILget unlock ability failed."); |
679 | } | 711 | } |
680 | } else { | 712 | } else { |
681 | printf("Unknown flashing command:%s\n", cmd); | 713 | printf("Unknown flashing command:%s\n", cmd); |
682 | strcpy(response, "FAILcommand not defined"); | 714 | strcpy(response, "FAILcommand not defined"); |
683 | } | 715 | } |
684 | fastboot_tx_write_more(response); | 716 | fastboot_tx_write_more(response); |
685 | 717 | ||
686 | /* Must call fastboot_none_resp before returning from the dispatch function | 718 | /* Must call fastboot_none_resp before returning from the dispatch function |
687 | * which uses fastboot_tx_write_more | 719 | * which uses fastboot_tx_write_more |
688 | */ | 720 | */ |
689 | fastboot_none_resp(response); | 721 | fastboot_none_resp(response); |
690 | } | 722 | } |
691 | #endif /* CONFIG_FASTBOOT_LOCK */ | 723 | #endif /* CONFIG_FASTBOOT_LOCK */ |
692 | 724 | ||
693 | #ifdef CONFIG_AVB_SUPPORT | 725 | #ifdef CONFIG_AVB_SUPPORT |
694 | static void set_active_avb(char *cmd, char *response) | 726 | static void set_active_avb(char *cmd, char *response) |
695 | { | 727 | { |
696 | AvbIOResult ret; | 728 | AvbIOResult ret; |
697 | int slot = 0; | 729 | int slot = 0; |
698 | 730 | ||
699 | if (!cmd) { | 731 | if (!cmd) { |
700 | pr_err("missing slot suffix\n"); | 732 | pr_err("missing slot suffix\n"); |
701 | fastboot_fail("missing slot suffix", response); | 733 | fastboot_fail("missing slot suffix", response); |
702 | return; | 734 | return; |
703 | } | 735 | } |
704 | 736 | ||
705 | slot = slotidx_from_suffix(cmd); | 737 | slot = slotidx_from_suffix(cmd); |
706 | 738 | ||
707 | if (slot < 0) { | 739 | if (slot < 0) { |
708 | fastboot_fail("err slot suffix", response); | 740 | fastboot_fail("err slot suffix", response); |
709 | return; | 741 | return; |
710 | } | 742 | } |
711 | 743 | ||
712 | ret = avb_ab_mark_slot_active(&fsl_avb_ab_ops, slot); | 744 | ret = avb_ab_mark_slot_active(&fsl_avb_ab_ops, slot); |
713 | if (ret != AVB_IO_RESULT_OK) | 745 | if (ret != AVB_IO_RESULT_OK) |
714 | fastboot_fail("avb IO error", response); | 746 | fastboot_fail("avb IO error", response); |
715 | else | 747 | else |
716 | fastboot_okay(NULL, response); | 748 | fastboot_okay(NULL, response); |
717 | 749 | ||
718 | return; | 750 | return; |
719 | } | 751 | } |
720 | #endif /*CONFIG_AVB_SUPPORT*/ | 752 | #endif /*CONFIG_AVB_SUPPORT*/ |
721 | 753 | ||
722 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) | 754 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
723 | static void flash(char *cmd, char *response) | 755 | static void flash(char *cmd, char *response) |
724 | { | 756 | { |
725 | if (!cmd) { | 757 | if (!cmd) { |
726 | pr_err("missing partition name"); | 758 | pr_err("missing partition name"); |
727 | fastboot_fail("missing partition name", response); | 759 | fastboot_fail("missing partition name", response); |
728 | return; | 760 | return; |
729 | } | 761 | } |
730 | 762 | ||
731 | /* Always enable image flash for Android Things. */ | 763 | /* Always enable image flash for Android Things. */ |
732 | #if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX) | 764 | #if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX) |
733 | int status; | 765 | int status; |
734 | status = fastboot_get_lock_stat(); | 766 | status = fastboot_get_lock_stat(); |
735 | 767 | ||
736 | if (status == FASTBOOT_LOCK) { | 768 | if (status == FASTBOOT_LOCK) { |
737 | pr_err("device is LOCKed!\n"); | 769 | pr_err("device is LOCKed!\n"); |
738 | fastboot_fail("device is locked.", response); | 770 | fastboot_fail("device is locked.", response); |
739 | return; | 771 | return; |
740 | 772 | ||
741 | } else if (status == FASTBOOT_LOCK_ERROR) { | 773 | } else if (status == FASTBOOT_LOCK_ERROR) { |
742 | pr_err("write lock status into device!\n"); | 774 | pr_err("write lock status into device!\n"); |
743 | fastboot_set_lock_stat(FASTBOOT_LOCK); | 775 | fastboot_set_lock_stat(FASTBOOT_LOCK); |
744 | fastboot_fail("device is locked.", response); | 776 | fastboot_fail("device is locked.", response); |
745 | return; | 777 | return; |
746 | } | 778 | } |
747 | #endif | 779 | #endif |
748 | 780 | ||
749 | fastboot_process_flash(cmd, fastboot_buf_addr, | 781 | fastboot_process_flash(cmd, fastboot_buf_addr, |
750 | fastboot_bytes_received, response); | 782 | fastboot_bytes_received, response); |
751 | 783 | ||
752 | #if defined(CONFIG_FASTBOOT_LOCK) | 784 | #if defined(CONFIG_FASTBOOT_LOCK) |
753 | if (strncmp(cmd, "gpt", 3) == 0) { | 785 | if (strncmp(cmd, "gpt", 3) == 0) { |
754 | int gpt_valid = 0; | 786 | int gpt_valid = 0; |
755 | gpt_valid = partition_table_valid(); | 787 | gpt_valid = partition_table_valid(); |
756 | /* If gpt is valid, load partitons table into memory. | 788 | /* If gpt is valid, load partitons table into memory. |
757 | So if the next command is "fastboot reboot bootloader", | 789 | So if the next command is "fastboot reboot bootloader", |
758 | it can find the "misc" partition to r/w. */ | 790 | it can find the "misc" partition to r/w. */ |
759 | if(gpt_valid) { | 791 | if(gpt_valid) { |
760 | fastboot_load_partitions(); | 792 | fastboot_load_partitions(); |
761 | /* Unlock device if the gpt is valid */ | 793 | /* Unlock device if the gpt is valid */ |
762 | do_fastboot_unlock(true); | 794 | do_fastboot_unlock(true); |
763 | } | 795 | } |
764 | } | 796 | } |
765 | 797 | ||
766 | #endif | 798 | #endif |
767 | } | 799 | } |
768 | 800 | ||
769 | static void erase(char *cmd, char *response) | 801 | static void erase(char *cmd, char *response) |
770 | { | 802 | { |
771 | if (!cmd) { | 803 | if (!cmd) { |
772 | pr_err("missing partition name"); | 804 | pr_err("missing partition name"); |
773 | fastboot_fail("missing partition name", response); | 805 | fastboot_fail("missing partition name", response); |
774 | return; | 806 | return; |
775 | } | 807 | } |
776 | 808 | ||
777 | #if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX) | 809 | #if defined(CONFIG_FASTBOOT_LOCK) && !defined(CONFIG_AVB_ATX) |
778 | FbLockState status; | 810 | FbLockState status; |
779 | status = fastboot_get_lock_stat(); | 811 | status = fastboot_get_lock_stat(); |
780 | if (status == FASTBOOT_LOCK) { | 812 | if (status == FASTBOOT_LOCK) { |
781 | pr_err("device is LOCKed!\n"); | 813 | pr_err("device is LOCKed!\n"); |
782 | fastboot_fail("device is locked.", response); | 814 | fastboot_fail("device is locked.", response); |
783 | return; | 815 | return; |
784 | } else if (status == FASTBOOT_LOCK_ERROR) { | 816 | } else if (status == FASTBOOT_LOCK_ERROR) { |
785 | pr_err("write lock status into device!\n"); | 817 | pr_err("write lock status into device!\n"); |
786 | fastboot_set_lock_stat(FASTBOOT_LOCK); | 818 | fastboot_set_lock_stat(FASTBOOT_LOCK); |
787 | fastboot_fail("device is locked.", response); | 819 | fastboot_fail("device is locked.", response); |
788 | return; | 820 | return; |
789 | } | 821 | } |
790 | #endif | 822 | #endif |
791 | fastboot_process_erase(cmd, response); | 823 | fastboot_process_erase(cmd, response); |
792 | } | 824 | } |
793 | #endif | 825 | #endif |
794 | 826 | ||
795 | /** | 827 | /** |
796 | * fastboot_set_reboot_flag() - Set flag to indicate reboot-bootloader | 828 | * fastboot_set_reboot_flag() - Set flag to indicate reboot-bootloader |
797 | * | 829 | * |
798 | * This is a redefinition, since BSP dose not need the function of | 830 | * This is a redefinition, since BSP dose not need the function of |
799 | * "reboot into bootloader", and with BCB support, the flag can be | 831 | * "reboot into bootloader", and with BCB support, the flag can be |
800 | * set with another way. Redefine this function to override the weak | 832 | * set with another way. Redefine this function to override the weak |
801 | * definition to avoid error return value. | 833 | * definition to avoid error return value. |
802 | */ | 834 | */ |
803 | int fastboot_set_reboot_flag(void) | 835 | int fastboot_set_reboot_flag(void) |
804 | { | 836 | { |
805 | return 0; | 837 | return 0; |
806 | } | 838 | } |
807 | 839 | ||
808 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 840 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
809 | /** | 841 | /** |
810 | * run_ucmd() - Execute the UCmd command | 842 | * run_ucmd() - Execute the UCmd command |
811 | * | 843 | * |
812 | * @cmd_parameter: Pointer to command parameter | 844 | * @cmd_parameter: Pointer to command parameter |
813 | * @response: Pointer to fastboot response buffer | 845 | * @response: Pointer to fastboot response buffer |
814 | */ | 846 | */ |
815 | static void run_ucmd(char *cmd_parameter, char *response) | 847 | static void run_ucmd(char *cmd_parameter, char *response) |
816 | { | 848 | { |
817 | if (!cmd_parameter) { | 849 | if (!cmd_parameter) { |
818 | pr_err("missing slot suffix\n"); | 850 | pr_err("missing slot suffix\n"); |
819 | fastboot_fail("missing command", response); | 851 | fastboot_fail("missing command", response); |
820 | return; | 852 | return; |
821 | } | 853 | } |
822 | if(run_command(cmd_parameter, 0)) { | 854 | if(run_command(cmd_parameter, 0)) { |
823 | fastboot_fail("", response); | 855 | fastboot_fail("", response); |
824 | } else { | 856 | } else { |
825 | fastboot_okay(NULL, response); | 857 | fastboot_okay(NULL, response); |
826 | /* cmd may impact fastboot related environment*/ | 858 | /* cmd may impact fastboot related environment*/ |
827 | fastboot_setup(); | 859 | fastboot_setup(); |
828 | } | 860 | } |
829 | } | 861 | } |
830 | 862 | ||
831 | static char g_a_cmd_buff[64]; | 863 | static char g_a_cmd_buff[64]; |
832 | 864 | ||
833 | void fastboot_acmd_complete(void) | 865 | void fastboot_acmd_complete(void) |
834 | { | 866 | { |
835 | run_command(g_a_cmd_buff, 0); | 867 | run_command(g_a_cmd_buff, 0); |
836 | } | 868 | } |
837 | 869 | ||
838 | /** | 870 | /** |
839 | * run_acmd() - Execute the ACmd command | 871 | * run_acmd() - Execute the ACmd command |
840 | * | 872 | * |
841 | * @cmd_parameter: Pointer to command parameter | 873 | * @cmd_parameter: Pointer to command parameter |
842 | * @response: Pointer to fastboot response buffer | 874 | * @response: Pointer to fastboot response buffer |
843 | */ | 875 | */ |
844 | static void run_acmd(char *cmd_parameter, char *response) | 876 | static void run_acmd(char *cmd_parameter, char *response) |
845 | { | 877 | { |
846 | if (!cmd_parameter) { | 878 | if (!cmd_parameter) { |
847 | pr_err("missing slot suffix\n"); | 879 | pr_err("missing slot suffix\n"); |
848 | fastboot_fail("missing command", response); | 880 | fastboot_fail("missing command", response); |
849 | return; | 881 | return; |
850 | } | 882 | } |
851 | strcpy(g_a_cmd_buff, cmd_parameter); | 883 | strcpy(g_a_cmd_buff, cmd_parameter); |
852 | fastboot_okay(NULL, response); | 884 | fastboot_okay(NULL, response); |
853 | } | 885 | } |
854 | #endif | 886 | #endif |
855 | 887 | ||
856 | static const struct { | 888 | static const struct { |
857 | const char *command; | 889 | const char *command; |
858 | void (*dispatch)(char *cmd_parameter, char *response); | 890 | void (*dispatch)(char *cmd_parameter, char *response); |
859 | } commands[FASTBOOT_COMMAND_COUNT] = { | 891 | } commands[FASTBOOT_COMMAND_COUNT] = { |
860 | [FASTBOOT_COMMAND_REBOOT_BOOTLOADER] = { | 892 | [FASTBOOT_COMMAND_REBOOT_BOOTLOADER] = { |
861 | .command = "reboot-bootloader", | 893 | .command = "reboot-bootloader", |
862 | .dispatch = reboot_bootloader, | 894 | .dispatch = reboot_bootloader, |
863 | }, | 895 | }, |
864 | [FASTBOOT_COMMAND_UPLOAD] = { | 896 | [FASTBOOT_COMMAND_UPLOAD] = { |
865 | .command = "upload", | 897 | .command = "upload", |
866 | .dispatch = upload, | 898 | .dispatch = upload, |
867 | }, | 899 | }, |
868 | [FASTBOOT_COMMAND_GETSTAGED] = { | 900 | [FASTBOOT_COMMAND_GETSTAGED] = { |
869 | .command = "get_staged", | 901 | .command = "get_staged", |
870 | .dispatch = upload, | 902 | .dispatch = upload, |
871 | }, | 903 | }, |
872 | #if defined(CONFIG_FASTBOOT_LOCK) | 904 | #if defined(CONFIG_FASTBOOT_LOCK) |
873 | [FASTBOOT_COMMAND_FLASHING] = { | 905 | [FASTBOOT_COMMAND_FLASHING] = { |
874 | .command = "flashing", | 906 | .command = "flashing", |
875 | .dispatch = flashing, | 907 | .dispatch = flashing, |
876 | }, | 908 | }, |
877 | [FASTBOOT_COMMAND_OEM] = { | 909 | [FASTBOOT_COMMAND_OEM] = { |
878 | .command = "oem", | 910 | .command = "oem", |
879 | .dispatch = flashing, | 911 | .dispatch = flashing, |
880 | }, | 912 | }, |
881 | #endif | 913 | #endif |
882 | #ifdef CONFIG_AVB_SUPPORT | 914 | #ifdef CONFIG_AVB_SUPPORT |
883 | [FASTBOOT_COMMAND_SETACTIVE] = { | 915 | [FASTBOOT_COMMAND_SETACTIVE] = { |
884 | .command = "set_active", | 916 | .command = "set_active", |
885 | .dispatch = set_active_avb, | 917 | .dispatch = set_active_avb, |
886 | }, | 918 | }, |
887 | #endif | 919 | #endif |
888 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 920 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
889 | [FASTBOOT_COMMAND_UCMD] = { | 921 | [FASTBOOT_COMMAND_UCMD] = { |
890 | .command = "UCmd", | 922 | .command = "UCmd", |
891 | .dispatch = run_ucmd, | 923 | .dispatch = run_ucmd, |
892 | }, | 924 | }, |
893 | [FASTBOOT_COMMAND_ACMD] = { | 925 | [FASTBOOT_COMMAND_ACMD] = { |
894 | .command ="ACmd", | 926 | .command ="ACmd", |
895 | .dispatch = run_acmd, | 927 | .dispatch = run_acmd, |
896 | }, | 928 | }, |
897 | #endif | 929 | #endif |
898 | [FASTBOOT_COMMAND_REBOOT] = { | 930 | [FASTBOOT_COMMAND_REBOOT] = { |
899 | .command = "reboot", | 931 | .command = "reboot", |
900 | .dispatch = okay, | 932 | .dispatch = okay, |
901 | }, | 933 | }, |
902 | [FASTBOOT_COMMAND_GETVAR] = { | 934 | [FASTBOOT_COMMAND_GETVAR] = { |
903 | .command = "getvar", | 935 | .command = "getvar", |
904 | .dispatch = getvar, | 936 | .dispatch = getvar, |
905 | }, | 937 | }, |
906 | [FASTBOOT_COMMAND_DOWNLOAD] = { | 938 | [FASTBOOT_COMMAND_DOWNLOAD] = { |
907 | .command = "download", | 939 | .command = "download", |
908 | .dispatch = download, | 940 | .dispatch = download, |
909 | }, | 941 | }, |
910 | [FASTBOOT_COMMAND_BOOT] = { | 942 | [FASTBOOT_COMMAND_BOOT] = { |
911 | .command = "boot", | 943 | .command = "boot", |
912 | .dispatch = okay, | 944 | .dispatch = okay, |
913 | }, | 945 | }, |
914 | [FASTBOOT_COMMAND_CONTINUE] = { | 946 | [FASTBOOT_COMMAND_CONTINUE] = { |
915 | .command = "continue", | 947 | .command = "continue", |
916 | .dispatch = okay, | 948 | .dispatch = okay, |
917 | }, | 949 | }, |
918 | #ifdef CONFIG_FASTBOOT_FLASH | 950 | #ifdef CONFIG_FASTBOOT_FLASH |
919 | [FASTBOOT_COMMAND_FLASH] = { | 951 | [FASTBOOT_COMMAND_FLASH] = { |
920 | .command = "flash", | 952 | .command = "flash", |
921 | .dispatch = flash, | 953 | .dispatch = flash, |
922 | }, | 954 | }, |
923 | [FASTBOOT_COMMAND_ERASE] = { | 955 | [FASTBOOT_COMMAND_ERASE] = { |
924 | .command = "erase", | 956 | .command = "erase", |
925 | .dispatch = erase, | 957 | .dispatch = erase, |
926 | }, | 958 | }, |
927 | #endif | 959 | #endif |
928 | #ifdef CONFIG_AVB_ATX | 960 | #ifdef CONFIG_AVB_ATX |
929 | [FASTBOOT_COMMAND_STAGE] = { | 961 | [FASTBOOT_COMMAND_STAGE] = { |
930 | .command = "stage", | 962 | .command = "stage", |
931 | .dispatch = download, | 963 | .dispatch = download, |
964 | }, | ||
965 | #endif | ||
966 | #ifdef CONFIG_ANDROID_RECOVERY | ||
967 | [FASTBOOT_COMMAND_RECOVERY_FASTBOOT] = { | ||
968 | .command = "reboot-fastboot", | ||
969 | .dispatch = reboot_fastboot, | ||
932 | }, | 970 | }, |
933 | #endif | 971 | #endif |
934 | }; | 972 | }; |
935 | 973 | ||
936 | /** | 974 | /** |
937 | * fastboot_handle_command - Handle fastboot command | 975 | * fastboot_handle_command - Handle fastboot command |
938 | * | 976 | * |
939 | * @cmd_string: Pointer to command string | 977 | * @cmd_string: Pointer to command string |
940 | * @response: Pointer to fastboot response buffer | 978 | * @response: Pointer to fastboot response buffer |
941 | * | 979 | * |
942 | * Return: Executed command, or -1 if not recognized | 980 | * Return: Executed command, or -1 if not recognized |
943 | */ | 981 | */ |
944 | int fastboot_handle_command(char *cmd_string, char *response) | 982 | int fastboot_handle_command(char *cmd_string, char *response) |
945 | { | 983 | { |
946 | int i; | 984 | int i; |
947 | char *cmd_parameter; | 985 | char *cmd_parameter; |
948 | 986 | ||
949 | cmd_parameter = cmd_string; | 987 | cmd_parameter = cmd_string; |
950 | strsep(&cmd_parameter, ":"); | 988 | strsep(&cmd_parameter, ":"); |
951 | /* separate cmdstring for "fastboot oem/flashing" with a blank */ | 989 | /* separate cmdstring for "fastboot oem/flashing" with a blank */ |
952 | if(cmd_parameter == NULL) | 990 | if(cmd_parameter == NULL) |
953 | { | 991 | { |
954 | cmd_parameter = cmd_string; | 992 | cmd_parameter = cmd_string; |
955 | strsep(&cmd_parameter, " "); | 993 | strsep(&cmd_parameter, " "); |
956 | } | 994 | } |
957 | 995 | ||
958 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | 996 | for (i = 0; i < ARRAY_SIZE(commands); i++) { |
959 | if (commands[i].command != NULL && | 997 | if (commands[i].command != NULL && |
960 | !strcmp(commands[i].command, cmd_string)) { | 998 | !strcmp(commands[i].command, cmd_string)) { |
961 | if (commands[i].dispatch) { | 999 | if (commands[i].dispatch) { |
962 | commands[i].dispatch(cmd_parameter, | 1000 | commands[i].dispatch(cmd_parameter, |
963 | response); | 1001 | response); |
964 | return i; | 1002 | return i; |
965 | } else { | 1003 | } else { |
966 | break; | 1004 | break; |
967 | } | 1005 | } |
968 | } | 1006 | } |
969 | } | 1007 | } |
970 | 1008 | ||
971 | pr_err("command %s not recognized.\n", cmd_string); | 1009 | pr_err("command %s not recognized.\n", cmd_string); |
972 | fastboot_fail("unrecognized command", response); | 1010 | fastboot_fail("unrecognized command", response); |
973 | return -1; | 1011 | return -1; |
974 | } | 1012 | } |
975 | 1013 |
drivers/fastboot/fb_fsl/fb_fsl_getvar.c
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * Copyright 2019 NXP | 3 | * Copyright 2019 NXP |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <common.h> | 6 | #include <common.h> |
7 | #include <asm/mach-imx/sys_proto.h> | 7 | #include <asm/mach-imx/sys_proto.h> |
8 | #include <fb_fsl.h> | 8 | #include <fb_fsl.h> |
9 | #include <fastboot.h> | 9 | #include <fastboot.h> |
10 | #include <mmc.h> | 10 | #include <mmc.h> |
11 | #include <android_image.h> | 11 | #include <android_image.h> |
12 | #include <asm/bootm.h> | 12 | #include <asm/bootm.h> |
13 | #include <nand.h> | 13 | #include <nand.h> |
14 | #include <part.h> | 14 | #include <part.h> |
15 | #include <sparse_format.h> | 15 | #include <sparse_format.h> |
16 | #include <image-sparse.h> | 16 | #include <image-sparse.h> |
17 | #include <image.h> | 17 | #include <image.h> |
18 | #include <asm/mach-imx/boot_mode.h> | 18 | #include <asm/mach-imx/boot_mode.h> |
19 | #include <asm/arch/sys_proto.h> | 19 | #include <asm/arch/sys_proto.h> |
20 | #include <asm/setup.h> | 20 | #include <asm/setup.h> |
21 | #include <env.h> | 21 | #include <env.h> |
22 | #include <version.h> | 22 | #include <version.h> |
23 | 23 | ||
24 | #ifdef CONFIG_AVB_SUPPORT | 24 | #ifdef CONFIG_AVB_SUPPORT |
25 | #include <dt_table.h> | 25 | #include <dt_table.h> |
26 | #include <fsl_avb.h> | 26 | #include <fsl_avb.h> |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #ifdef CONFIG_ANDROID_THINGS_SUPPORT | 29 | #ifdef CONFIG_ANDROID_THINGS_SUPPORT |
30 | #include <asm-generic/gpio.h> | 30 | #include <asm-generic/gpio.h> |
31 | #include <asm/mach-imx/gpio.h> | 31 | #include <asm/mach-imx/gpio.h> |
32 | #include "../lib/avb/fsl/fsl_avbkey.h" | 32 | #include "../lib/avb/fsl/fsl_avbkey.h" |
33 | #include "../arch/arm/include/asm/mach-imx/hab.h" | 33 | #include "../arch/arm/include/asm/mach-imx/hab.h" |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #if defined(CONFIG_FASTBOOT_LOCK) | 36 | #if defined(CONFIG_FASTBOOT_LOCK) |
37 | #include "fastboot_lock_unlock.h" | 37 | #include "fastboot_lock_unlock.h" |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #include "fb_fsl_common.h" | 40 | #include "fb_fsl_common.h" |
41 | 41 | ||
42 | #ifdef CONFIG_IMX_TRUSTY_OS | 42 | #ifdef CONFIG_IMX_TRUSTY_OS |
43 | #include "u-boot/sha256.h" | 43 | #include "u-boot/sha256.h" |
44 | #include <trusty/libtipc.h> | 44 | #include <trusty/libtipc.h> |
45 | 45 | ||
46 | #define ATAP_UUID_SIZE 32 | 46 | #define ATAP_UUID_SIZE 32 |
47 | #define ATAP_UUID_STR_SIZE ((ATAP_UUID_SIZE*2) + 1) | 47 | #define ATAP_UUID_STR_SIZE ((ATAP_UUID_SIZE*2) + 1) |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) | 50 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) |
51 | #define FASTBOOT_COMMON_VAR_NUM 14 | 51 | #define FASTBOOT_COMMON_VAR_NUM 15 |
52 | #else | 52 | #else |
53 | #define FASTBOOT_COMMON_VAR_NUM 13 | 53 | #define FASTBOOT_COMMON_VAR_NUM 14 |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #define FASTBOOT_VAR_YES "yes" | 56 | #define FASTBOOT_VAR_YES "yes" |
57 | #define FASTBOOT_VAR_NO "no" | 57 | #define FASTBOOT_VAR_NO "no" |
58 | 58 | ||
59 | /* common variables of fastboot getvar command */ | 59 | /* common variables of fastboot getvar command */ |
60 | char *fastboot_common_var[FASTBOOT_COMMON_VAR_NUM] = { | 60 | char *fastboot_common_var[FASTBOOT_COMMON_VAR_NUM] = { |
61 | "version", | 61 | "version", |
62 | "version-bootloader", | 62 | "version-bootloader", |
63 | "version-baseband", | 63 | "version-baseband", |
64 | "product", | 64 | "product", |
65 | "secure", | 65 | "secure", |
66 | "max-download-size", | 66 | "max-download-size", |
67 | "erase-block-size", | 67 | "erase-block-size", |
68 | "logical-block-size", | 68 | "logical-block-size", |
69 | "unlocked", | 69 | "unlocked", |
70 | "off-mode-charge", | 70 | "off-mode-charge", |
71 | "battery-voltage", | 71 | "battery-voltage", |
72 | "variant", | 72 | "variant", |
73 | "battery-soc-ok", | 73 | "battery-soc-ok", |
74 | "is-userspace", | ||
74 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) | 75 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) |
75 | "baseboard_id" | 76 | "baseboard_id" |
76 | #endif | 77 | #endif |
77 | }; | 78 | }; |
78 | 79 | ||
79 | /* at-vboot-state variable list */ | 80 | /* at-vboot-state variable list */ |
80 | #ifdef CONFIG_AVB_ATX | 81 | #ifdef CONFIG_AVB_ATX |
81 | #define AT_VBOOT_STATE_VAR_NUM 6 | 82 | #define AT_VBOOT_STATE_VAR_NUM 6 |
82 | extern struct imx_sec_config_fuse_t const imx_sec_config_fuse; | 83 | extern struct imx_sec_config_fuse_t const imx_sec_config_fuse; |
83 | extern int fuse_read(u32 bank, u32 word, u32 *val); | 84 | extern int fuse_read(u32 bank, u32 word, u32 *val); |
84 | 85 | ||
85 | char *fastboot_at_vboot_state_var[AT_VBOOT_STATE_VAR_NUM] = { | 86 | char *fastboot_at_vboot_state_var[AT_VBOOT_STATE_VAR_NUM] = { |
86 | "bootloader-locked", | 87 | "bootloader-locked", |
87 | "bootloader-min-versions", | 88 | "bootloader-min-versions", |
88 | "avb-perm-attr-set", | 89 | "avb-perm-attr-set", |
89 | "avb-locked", | 90 | "avb-locked", |
90 | "avb-unlock-disabled", | 91 | "avb-unlock-disabled", |
91 | "avb-min-versions" | 92 | "avb-min-versions" |
92 | }; | 93 | }; |
93 | #endif | 94 | #endif |
94 | 95 | ||
95 | static int strcmp_l1(const char *s1, const char *s2) | 96 | static int strcmp_l1(const char *s1, const char *s2) |
96 | { | 97 | { |
97 | if (!s1 || !s2) | 98 | if (!s1 || !s2) |
98 | return -1; | 99 | return -1; |
99 | return strncmp(s1, s2, strlen(s1)); | 100 | return strncmp(s1, s2, strlen(s1)); |
100 | } | 101 | } |
101 | 102 | ||
102 | static bool is_slotvar(char *cmd) | 103 | static bool is_slotvar(char *cmd) |
103 | { | 104 | { |
104 | assert(cmd != NULL); | 105 | assert(cmd != NULL); |
105 | if (!strcmp_l1("has-slot:", cmd) || | 106 | if (!strcmp_l1("has-slot:", cmd) || |
106 | !strcmp_l1("slot-successful:", cmd) || | 107 | !strcmp_l1("slot-successful:", cmd) || |
107 | !strcmp_l1("slot-count", cmd) || | 108 | !strcmp_l1("slot-count", cmd) || |
108 | !strcmp_l1("slot-suffixes", cmd) || | 109 | !strcmp_l1("slot-suffixes", cmd) || |
109 | !strcmp_l1("current-slot", cmd) || | 110 | !strcmp_l1("current-slot", cmd) || |
110 | !strcmp_l1("slot-unbootable:", cmd) || | 111 | !strcmp_l1("slot-unbootable:", cmd) || |
111 | !strcmp_l1("slot-retry-count:", cmd)) | 112 | !strcmp_l1("slot-retry-count:", cmd)) |
112 | return true; | 113 | return true; |
113 | return false; | 114 | return false; |
114 | } | 115 | } |
115 | 116 | ||
116 | static char serial[IMX_SERIAL_LEN]; | 117 | static char serial[IMX_SERIAL_LEN]; |
117 | 118 | ||
118 | char *get_serial(void) | 119 | char *get_serial(void) |
119 | { | 120 | { |
120 | #ifdef CONFIG_SERIAL_TAG | 121 | #ifdef CONFIG_SERIAL_TAG |
121 | struct tag_serialnr serialnr; | 122 | struct tag_serialnr serialnr; |
122 | memset(serial, 0, IMX_SERIAL_LEN); | 123 | memset(serial, 0, IMX_SERIAL_LEN); |
123 | 124 | ||
124 | get_board_serial(&serialnr); | 125 | get_board_serial(&serialnr); |
125 | sprintf(serial, "%08x%08x", serialnr.high, serialnr.low); | 126 | sprintf(serial, "%08x%08x", serialnr.high, serialnr.low); |
126 | return serial; | 127 | return serial; |
127 | #else | 128 | #else |
128 | return NULL; | 129 | return NULL; |
129 | #endif | 130 | #endif |
130 | } | 131 | } |
131 | 132 | ||
132 | #if !defined(PRODUCT_NAME) | 133 | #if !defined(PRODUCT_NAME) |
133 | #define PRODUCT_NAME "NXP i.MX" | 134 | #define PRODUCT_NAME "NXP i.MX" |
134 | #endif | 135 | #endif |
135 | 136 | ||
136 | #if !defined(VARIANT_NAME) | 137 | #if !defined(VARIANT_NAME) |
137 | #define VARIANT_NAME "NXP i.MX" | 138 | #define VARIANT_NAME "NXP i.MX" |
138 | #endif | 139 | #endif |
139 | 140 | ||
140 | #ifdef CONFIG_IMX_TRUSTY_OS | 141 | #ifdef CONFIG_IMX_TRUSTY_OS |
141 | static void uuid_hex2string(uint8_t *uuid, char* buf, uint32_t uuid_len, uint32_t uuid_strlen) { | 142 | static void uuid_hex2string(uint8_t *uuid, char* buf, uint32_t uuid_len, uint32_t uuid_strlen) { |
142 | uint32_t i; | 143 | uint32_t i; |
143 | if (!uuid || !buf) | 144 | if (!uuid || !buf) |
144 | return; | 145 | return; |
145 | char *cp = buf; | 146 | char *cp = buf; |
146 | char *buf_end = buf + uuid_strlen; | 147 | char *buf_end = buf + uuid_strlen; |
147 | for (i = 0; i < uuid_len; i++) { | 148 | for (i = 0; i < uuid_len; i++) { |
148 | cp += snprintf(cp, buf_end - cp, "%02x", uuid[i]); | 149 | cp += snprintf(cp, buf_end - cp, "%02x", uuid[i]); |
149 | } | 150 | } |
150 | } | 151 | } |
151 | #endif | 152 | #endif |
152 | 153 | ||
153 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) | 154 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) |
154 | int get_imx8m_baseboard_id(void); | 155 | int get_imx8m_baseboard_id(void); |
155 | #endif | 156 | #endif |
156 | 157 | ||
157 | static int get_single_var(char *cmd, char *response) | 158 | static int get_single_var(char *cmd, char *response) |
158 | { | 159 | { |
159 | char *str = cmd; | 160 | char *str = cmd; |
160 | int chars_left; | 161 | int chars_left; |
161 | const char *s; | 162 | const char *s; |
162 | struct mmc *mmc; | 163 | struct mmc *mmc; |
163 | int mmc_dev_no; | 164 | int mmc_dev_no; |
164 | int blksz; | 165 | int blksz; |
165 | 166 | ||
166 | chars_left = FASTBOOT_RESPONSE_LEN - strlen(response) - 1; | 167 | chars_left = FASTBOOT_RESPONSE_LEN - strlen(response) - 1; |
167 | 168 | ||
168 | if ((str = strstr(cmd, "partition-size:"))) { | 169 | if ((str = strstr(cmd, "partition-size:"))) { |
169 | str +=strlen("partition-size:"); | 170 | str +=strlen("partition-size:"); |
170 | struct fastboot_ptentry* fb_part; | 171 | struct fastboot_ptentry* fb_part; |
171 | fb_part = fastboot_flash_find_ptn(str); | 172 | fb_part = fastboot_flash_find_ptn(str); |
172 | if (!fb_part) { | 173 | if (!fb_part) { |
173 | strncat(response, "Wrong partition name.", chars_left); | 174 | strncat(response, "Wrong partition name.", chars_left); |
174 | fastboot_flash_dump_ptn(); | 175 | fastboot_flash_dump_ptn(); |
175 | return -1; | 176 | return -1; |
176 | } else { | 177 | } else { |
177 | snprintf(response + strlen(response), chars_left, | 178 | snprintf(response + strlen(response), chars_left, |
178 | "0x%llx", | 179 | "0x%llx", |
179 | (uint64_t)fb_part->length * get_block_size()); | 180 | (uint64_t)fb_part->length * get_block_size()); |
180 | } | 181 | } |
181 | } else if ((str = strstr(cmd, "partition-type:"))) { | 182 | } else if ((str = strstr(cmd, "partition-type:"))) { |
182 | str +=strlen("partition-type:"); | 183 | str +=strlen("partition-type:"); |
183 | struct fastboot_ptentry* fb_part; | 184 | struct fastboot_ptentry* fb_part; |
184 | fb_part = fastboot_flash_find_ptn(str); | 185 | fb_part = fastboot_flash_find_ptn(str); |
185 | if (!fb_part) { | 186 | if (!fb_part) { |
186 | strncat(response, "Wrong partition name.", chars_left); | 187 | strncat(response, "Wrong partition name.", chars_left); |
187 | fastboot_flash_dump_ptn(); | 188 | fastboot_flash_dump_ptn(); |
188 | return -1; | 189 | return -1; |
189 | } else { | 190 | } else { |
190 | strncat(response, fb_part->fstype, chars_left); | 191 | strncat(response, fb_part->fstype, chars_left); |
191 | } | 192 | } |
192 | } else if ((str = strstr(cmd, "is-logical:"))) { | 193 | } else if ((str = strstr(cmd, "is-logical:"))) { |
193 | str +=strlen("is-logical:"); | 194 | str +=strlen("is-logical:"); |
194 | struct fastboot_ptentry* fb_part; | 195 | struct fastboot_ptentry* fb_part; |
195 | fb_part = fastboot_flash_find_ptn(str); | 196 | fb_part = fastboot_flash_find_ptn(str); |
196 | if (!fb_part) { | 197 | if (!fb_part) { |
197 | return -1; | 198 | return -1; |
198 | } else { | 199 | } else { |
199 | snprintf(response + strlen(response), chars_left, "no"); | 200 | snprintf(response + strlen(response), chars_left, "no"); |
200 | } | 201 | } |
201 | } else if (!strcmp_l1("version-baseband", cmd)) { | 202 | } else if (!strcmp_l1("version-baseband", cmd)) { |
202 | strncat(response, "N/A", chars_left); | 203 | strncat(response, "N/A", chars_left); |
203 | } else if (!strcmp_l1("version-bootloader", cmd) || | 204 | } else if (!strcmp_l1("version-bootloader", cmd) || |
204 | !strcmp_l1("bootloader-version", cmd)) { | 205 | !strcmp_l1("bootloader-version", cmd)) { |
205 | strncat(response, U_BOOT_VERSION, chars_left); | 206 | strncat(response, U_BOOT_VERSION, chars_left); |
206 | } else if (!strcmp_l1("version", cmd)) { | 207 | } else if (!strcmp_l1("version", cmd)) { |
207 | strncat(response, FASTBOOT_VERSION, chars_left); | 208 | strncat(response, FASTBOOT_VERSION, chars_left); |
208 | } else if (!strcmp_l1("battery-voltage", cmd)) { | 209 | } else if (!strcmp_l1("battery-voltage", cmd)) { |
209 | strncat(response, "0mV", chars_left); | 210 | strncat(response, "0mV", chars_left); |
210 | } else if (!strcmp_l1("battery-soc-ok", cmd)) { | 211 | } else if (!strcmp_l1("battery-soc-ok", cmd)) { |
211 | strncat(response, "yes", chars_left); | 212 | strncat(response, "yes", chars_left); |
212 | } else if (!strcmp_l1("variant", cmd)) { | 213 | } else if (!strcmp_l1("variant", cmd)) { |
213 | strncat(response, VARIANT_NAME, chars_left); | 214 | strncat(response, VARIANT_NAME, chars_left); |
214 | } else if (!strcmp_l1("off-mode-charge", cmd)) { | 215 | } else if (!strcmp_l1("off-mode-charge", cmd)) { |
215 | strncat(response, "1", chars_left); | 216 | strncat(response, "1", chars_left); |
217 | } else if (!strcmp_l1("is-userspace", cmd)) { | ||
218 | strncat(response, FASTBOOT_VAR_NO, chars_left); | ||
216 | } else if (!strcmp_l1("downloadsize", cmd) || | 219 | } else if (!strcmp_l1("downloadsize", cmd) || |
217 | !strcmp_l1("max-download-size", cmd)) { | 220 | !strcmp_l1("max-download-size", cmd)) { |
218 | 221 | ||
219 | snprintf(response + strlen(response), chars_left, "0x%x", CONFIG_FASTBOOT_BUF_SIZE); | 222 | snprintf(response + strlen(response), chars_left, "0x%x", CONFIG_FASTBOOT_BUF_SIZE); |
220 | } else if (!strcmp_l1("erase-block-size", cmd)) { | 223 | } else if (!strcmp_l1("erase-block-size", cmd)) { |
221 | mmc_dev_no = mmc_get_env_dev(); | 224 | mmc_dev_no = mmc_get_env_dev(); |
222 | mmc = find_mmc_device(mmc_dev_no); | 225 | mmc = find_mmc_device(mmc_dev_no); |
223 | blksz = get_block_size(); | 226 | blksz = get_block_size(); |
224 | snprintf(response + strlen(response), chars_left, "0x%x", | 227 | snprintf(response + strlen(response), chars_left, "0x%x", |
225 | (blksz * mmc->erase_grp_size)); | 228 | (blksz * mmc->erase_grp_size)); |
226 | } else if (!strcmp_l1("logical-block-size", cmd)) { | 229 | } else if (!strcmp_l1("logical-block-size", cmd)) { |
227 | blksz = get_block_size(); | 230 | blksz = get_block_size(); |
228 | snprintf(response + strlen(response), chars_left, "0x%x", blksz); | 231 | snprintf(response + strlen(response), chars_left, "0x%x", blksz); |
229 | } else if (!strcmp_l1("serialno", cmd)) { | 232 | } else if (!strcmp_l1("serialno", cmd)) { |
230 | s = get_serial(); | 233 | s = get_serial(); |
231 | if (s) | 234 | if (s) |
232 | strncat(response, s, chars_left); | 235 | strncat(response, s, chars_left); |
233 | else { | 236 | else { |
234 | strncat(response, "FAILValue not set", chars_left); | 237 | strncat(response, "FAILValue not set", chars_left); |
235 | return -1; | 238 | return -1; |
236 | } | 239 | } |
237 | } else if (!strcmp_l1("product", cmd)) { | 240 | } else if (!strcmp_l1("product", cmd)) { |
238 | strncat(response, PRODUCT_NAME, chars_left); | 241 | strncat(response, PRODUCT_NAME, chars_left); |
239 | } | 242 | } |
240 | #ifdef CONFIG_IMX_TRUSTY_OS | 243 | #ifdef CONFIG_IMX_TRUSTY_OS |
241 | else if(!strcmp_l1("at-attest-uuid", cmd)) { | 244 | else if(!strcmp_l1("at-attest-uuid", cmd)) { |
242 | char *uuid; | 245 | char *uuid; |
243 | char uuid_str[ATAP_UUID_STR_SIZE]; | 246 | char uuid_str[ATAP_UUID_STR_SIZE]; |
244 | if (trusty_atap_read_uuid_str(&uuid)) { | 247 | if (trusty_atap_read_uuid_str(&uuid)) { |
245 | printf("ERROR read uuid failed!\n"); | 248 | printf("ERROR read uuid failed!\n"); |
246 | strncat(response, "FAILCannot get uuid!", chars_left); | 249 | strncat(response, "FAILCannot get uuid!", chars_left); |
247 | return -1; | 250 | return -1; |
248 | } else { | 251 | } else { |
249 | uuid_hex2string((uint8_t*)uuid, uuid_str,ATAP_UUID_SIZE, ATAP_UUID_STR_SIZE); | 252 | uuid_hex2string((uint8_t*)uuid, uuid_str,ATAP_UUID_SIZE, ATAP_UUID_STR_SIZE); |
250 | strncat(response, uuid_str, chars_left); | 253 | strncat(response, uuid_str, chars_left); |
251 | trusty_free(uuid); | 254 | trusty_free(uuid); |
252 | } | 255 | } |
253 | } | 256 | } |
254 | else if(!strcmp_l1("at-attest-dh", cmd)) { | 257 | else if(!strcmp_l1("at-attest-dh", cmd)) { |
255 | strncat(response, "1:P256,2:curve25519", chars_left); | 258 | strncat(response, "1:P256,2:curve25519", chars_left); |
256 | } | 259 | } |
257 | #endif | 260 | #endif |
258 | #if defined(CONFIG_FASTBOOT_LOCK) | 261 | #if defined(CONFIG_FASTBOOT_LOCK) |
259 | else if (!strcmp_l1("secure", cmd)) { | 262 | else if (!strcmp_l1("secure", cmd)) { |
260 | strncat(response, FASTBOOT_VAR_YES, chars_left); | 263 | strncat(response, FASTBOOT_VAR_YES, chars_left); |
261 | } else if (!strcmp_l1("unlocked",cmd)){ | 264 | } else if (!strcmp_l1("unlocked",cmd)){ |
262 | int status = fastboot_get_lock_stat(); | 265 | int status = fastboot_get_lock_stat(); |
263 | if (status == FASTBOOT_UNLOCK) { | 266 | if (status == FASTBOOT_UNLOCK) { |
264 | strncat(response, FASTBOOT_VAR_YES, chars_left); | 267 | strncat(response, FASTBOOT_VAR_YES, chars_left); |
265 | } else { | 268 | } else { |
266 | strncat(response, FASTBOOT_VAR_NO, chars_left); | 269 | strncat(response, FASTBOOT_VAR_NO, chars_left); |
267 | } | 270 | } |
268 | } | 271 | } |
269 | #else | 272 | #else |
270 | else if (!strcmp_l1("secure", cmd)) { | 273 | else if (!strcmp_l1("secure", cmd)) { |
271 | strncat(response, FASTBOOT_VAR_NO, chars_left); | 274 | strncat(response, FASTBOOT_VAR_NO, chars_left); |
272 | } else if (!strcmp_l1("unlocked",cmd)) { | 275 | } else if (!strcmp_l1("unlocked",cmd)) { |
273 | strncat(response, FASTBOOT_VAR_NO, chars_left); | 276 | strncat(response, FASTBOOT_VAR_NO, chars_left); |
274 | } | 277 | } |
275 | #endif | 278 | #endif |
276 | else if (is_slotvar(cmd)) { | 279 | else if (is_slotvar(cmd)) { |
277 | #ifdef CONFIG_AVB_SUPPORT | 280 | #ifdef CONFIG_AVB_SUPPORT |
278 | if (get_slotvar_avb(&fsl_avb_ab_ops, cmd, | 281 | if (get_slotvar_avb(&fsl_avb_ab_ops, cmd, |
279 | response + strlen(response), chars_left + 1) < 0) | 282 | response + strlen(response), chars_left + 1) < 0) |
280 | return -1; | 283 | return -1; |
281 | #else | 284 | #else |
282 | strncat(response, FASTBOOT_VAR_NO, chars_left); | 285 | strncat(response, FASTBOOT_VAR_NO, chars_left); |
283 | #endif | 286 | #endif |
284 | } | 287 | } |
285 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) | 288 | #if defined(CONFIG_ANDROID_THINGS_SUPPORT) && defined(CONFIG_ARCH_IMX8M) |
286 | else if (!strcmp_l1("baseboard_id", cmd)) { | 289 | else if (!strcmp_l1("baseboard_id", cmd)) { |
287 | int baseboard_id; | 290 | int baseboard_id; |
288 | 291 | ||
289 | baseboard_id = get_imx8m_baseboard_id(); | 292 | baseboard_id = get_imx8m_baseboard_id(); |
290 | if (baseboard_id < 0) { | 293 | if (baseboard_id < 0) { |
291 | printf("Get baseboard id failed!\n"); | 294 | printf("Get baseboard id failed!\n"); |
292 | strncat(response, "Get baseboard id failed!", chars_left); | 295 | strncat(response, "Get baseboard id failed!", chars_left); |
293 | return -1; | 296 | return -1; |
294 | } else | 297 | } else |
295 | snprintf(response + strlen(response), chars_left, "0x%x", baseboard_id); | 298 | snprintf(response + strlen(response), chars_left, "0x%x", baseboard_id); |
296 | } | 299 | } |
297 | #endif | 300 | #endif |
298 | #ifdef CONFIG_AVB_ATX | 301 | #ifdef CONFIG_AVB_ATX |
299 | else if (!strcmp_l1("bootloader-locked", cmd)) { | 302 | else if (!strcmp_l1("bootloader-locked", cmd)) { |
300 | 303 | ||
301 | /* Below is basically copied from is_hab_enabled() */ | 304 | /* Below is basically copied from is_hab_enabled() */ |
302 | struct imx_sec_config_fuse_t *fuse = | 305 | struct imx_sec_config_fuse_t *fuse = |
303 | (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; | 306 | (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; |
304 | uint32_t reg; | 307 | uint32_t reg; |
305 | int ret; | 308 | int ret; |
306 | 309 | ||
307 | /* Read the secure boot status from fuse. */ | 310 | /* Read the secure boot status from fuse. */ |
308 | ret = fuse_read(fuse->bank, fuse->word, ®); | 311 | ret = fuse_read(fuse->bank, fuse->word, ®); |
309 | if (ret) { | 312 | if (ret) { |
310 | printf("\nSecure boot fuse read error!\n"); | 313 | printf("\nSecure boot fuse read error!\n"); |
311 | strncat(response, "Secure boot fuse read error!", chars_left); | 314 | strncat(response, "Secure boot fuse read error!", chars_left); |
312 | return -1; | 315 | return -1; |
313 | } | 316 | } |
314 | /* Check if the secure boot bit is enabled */ | 317 | /* Check if the secure boot bit is enabled */ |
315 | if ((reg & 0x2000000) == 0x2000000) | 318 | if ((reg & 0x2000000) == 0x2000000) |
316 | strncat(response, "1", chars_left); | 319 | strncat(response, "1", chars_left); |
317 | else | 320 | else |
318 | strncat(response, "0", chars_left); | 321 | strncat(response, "0", chars_left); |
319 | } else if (!strcmp_l1("bootloader-min-versions", cmd)) { | 322 | } else if (!strcmp_l1("bootloader-min-versions", cmd)) { |
320 | #ifndef CONFIG_ARM64 | 323 | #ifndef CONFIG_ARM64 |
321 | /* We don't support bootloader rbindex protection for | 324 | /* We don't support bootloader rbindex protection for |
322 | * ARM32(like imx7d) and the format is: "bootloader,tee". */ | 325 | * ARM32(like imx7d) and the format is: "bootloader,tee". */ |
323 | strncat(response, "-1,-1", chars_left); | 326 | strncat(response, "-1,-1", chars_left); |
324 | 327 | ||
325 | #elif defined(CONFIG_DUAL_BOOTLOADER) | 328 | #elif defined(CONFIG_DUAL_BOOTLOADER) |
326 | /* Rbindex protection for bootloader is supported only when the | 329 | /* Rbindex protection for bootloader is supported only when the |
327 | * 'dual bootloader' feature is enabled. U-boot will get the rbindx | 330 | * 'dual bootloader' feature is enabled. U-boot will get the rbindx |
328 | * from RAM which is passed by spl because we can only get the rbindex | 331 | * from RAM which is passed by spl because we can only get the rbindex |
329 | * at spl stage. The format in this case is: "spl,atf,tee,u-boot". | 332 | * at spl stage. The format in this case is: "spl,atf,tee,u-boot". |
330 | */ | 333 | */ |
331 | struct bl_rbindex_package *bl_rbindex; | 334 | struct bl_rbindex_package *bl_rbindex; |
332 | uint32_t rbindex; | 335 | uint32_t rbindex; |
333 | 336 | ||
334 | bl_rbindex = (struct bl_rbindex_package *)BL_RBINDEX_LOAD_ADDR; | 337 | bl_rbindex = (struct bl_rbindex_package *)BL_RBINDEX_LOAD_ADDR; |
335 | if (!strncmp(bl_rbindex->magic, BL_RBINDEX_MAGIC, | 338 | if (!strncmp(bl_rbindex->magic, BL_RBINDEX_MAGIC, |
336 | BL_RBINDEX_MAGIC_LEN)) { | 339 | BL_RBINDEX_MAGIC_LEN)) { |
337 | rbindex = bl_rbindex->rbindex; | 340 | rbindex = bl_rbindex->rbindex; |
338 | snprintf(response + strlen(response), chars_left, | 341 | snprintf(response + strlen(response), chars_left, |
339 | "-1,%d,%d,%d",rbindex, rbindex, rbindex); | 342 | "-1,%d,%d,%d",rbindex, rbindex, rbindex); |
340 | } else { | 343 | } else { |
341 | printf("Error bootloader rbindex magic!\n"); | 344 | printf("Error bootloader rbindex magic!\n"); |
342 | strncat(response, "Get bootloader rbindex fail!", chars_left); | 345 | strncat(response, "Get bootloader rbindex fail!", chars_left); |
343 | return -1; | 346 | return -1; |
344 | } | 347 | } |
345 | #else | 348 | #else |
346 | /* Return -1 for all partition if 'dual bootloader' feature | 349 | /* Return -1 for all partition if 'dual bootloader' feature |
347 | * is not enabled */ | 350 | * is not enabled */ |
348 | strncat(response, "-1,-1,-1,-1", chars_left); | 351 | strncat(response, "-1,-1,-1,-1", chars_left); |
349 | #endif | 352 | #endif |
350 | } else if (!strcmp_l1("avb-perm-attr-set", cmd)) { | 353 | } else if (!strcmp_l1("avb-perm-attr-set", cmd)) { |
351 | if (perm_attr_are_fused()) | 354 | if (perm_attr_are_fused()) |
352 | strncat(response, "1", chars_left); | 355 | strncat(response, "1", chars_left); |
353 | else | 356 | else |
354 | strncat(response, "0", chars_left); | 357 | strncat(response, "0", chars_left); |
355 | } else if (!strcmp_l1("avb-locked", cmd)) { | 358 | } else if (!strcmp_l1("avb-locked", cmd)) { |
356 | FbLockState status; | 359 | FbLockState status; |
357 | 360 | ||
358 | status = fastboot_get_lock_stat(); | 361 | status = fastboot_get_lock_stat(); |
359 | if (status == FASTBOOT_LOCK) | 362 | if (status == FASTBOOT_LOCK) |
360 | strncat(response, "1", chars_left); | 363 | strncat(response, "1", chars_left); |
361 | else if (status == FASTBOOT_UNLOCK) | 364 | else if (status == FASTBOOT_UNLOCK) |
362 | strncat(response, "0", chars_left); | 365 | strncat(response, "0", chars_left); |
363 | else { | 366 | else { |
364 | printf("Get lock state error!\n"); | 367 | printf("Get lock state error!\n"); |
365 | strncat(response, "Get lock state failed!", chars_left); | 368 | strncat(response, "Get lock state failed!", chars_left); |
366 | return -1; | 369 | return -1; |
367 | } | 370 | } |
368 | } else if (!strcmp_l1("avb-unlock-disabled", cmd)) { | 371 | } else if (!strcmp_l1("avb-unlock-disabled", cmd)) { |
369 | if (at_unlock_vboot_is_disabled()) | 372 | if (at_unlock_vboot_is_disabled()) |
370 | strncat(response, "1", chars_left); | 373 | strncat(response, "1", chars_left); |
371 | else | 374 | else |
372 | strncat(response, "0", chars_left); | 375 | strncat(response, "0", chars_left); |
373 | } else if (!strcmp_l1("avb-min-versions", cmd)) { | 376 | } else if (!strcmp_l1("avb-min-versions", cmd)) { |
374 | int i = 0; | 377 | int i = 0; |
375 | /* rbindex location/value can be very large | 378 | /* rbindex location/value can be very large |
376 | * number so we reserve enough space here. | 379 | * number so we reserve enough space here. |
377 | */ | 380 | */ |
378 | char buffer[35]; | 381 | char buffer[35]; |
379 | uint32_t rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2]; | 382 | uint32_t rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2]; |
380 | uint32_t location; | 383 | uint32_t location; |
381 | uint64_t rbindex; | 384 | uint64_t rbindex; |
382 | 385 | ||
383 | memset(buffer, '\0', sizeof(buffer)); | 386 | memset(buffer, '\0', sizeof(buffer)); |
384 | 387 | ||
385 | /* Set rbindex locations. */ | 388 | /* Set rbindex locations. */ |
386 | for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++) | 389 | for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS; i++) |
387 | rbindex_location[i] = i; | 390 | rbindex_location[i] = i; |
388 | 391 | ||
389 | /* Set Android Things key version rbindex locations */ | 392 | /* Set Android Things key version rbindex locations */ |
390 | rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS] | 393 | rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS] |
391 | = AVB_ATX_PIK_VERSION_LOCATION; | 394 | = AVB_ATX_PIK_VERSION_LOCATION; |
392 | rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1] | 395 | rbindex_location[AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1] |
393 | = AVB_ATX_PSK_VERSION_LOCATION; | 396 | = AVB_ATX_PSK_VERSION_LOCATION; |
394 | 397 | ||
395 | /* Read rollback index and set the reponse*/ | 398 | /* Read rollback index and set the reponse*/ |
396 | for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2; i++) { | 399 | for (i = 0; i < AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 2; i++) { |
397 | location = rbindex_location[i]; | 400 | location = rbindex_location[i]; |
398 | if (fsl_avb_ops.read_rollback_index(&fsl_avb_ops, | 401 | if (fsl_avb_ops.read_rollback_index(&fsl_avb_ops, |
399 | location, &rbindex) | 402 | location, &rbindex) |
400 | != AVB_IO_RESULT_OK) { | 403 | != AVB_IO_RESULT_OK) { |
401 | printf("Read rollback index error!\n"); | 404 | printf("Read rollback index error!\n"); |
402 | snprintf(response, FASTBOOT_RESPONSE_LEN, | 405 | snprintf(response, FASTBOOT_RESPONSE_LEN, |
403 | "INFOread rollback index error when get avb-min-versions"); | 406 | "INFOread rollback index error when get avb-min-versions"); |
404 | return -1; | 407 | return -1; |
405 | } | 408 | } |
406 | /* Generate the "location:value" pair */ | 409 | /* Generate the "location:value" pair */ |
407 | snprintf(buffer, sizeof(buffer), "%d:%lld", location, rbindex); | 410 | snprintf(buffer, sizeof(buffer), "%d:%lld", location, rbindex); |
408 | if (i != AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1) | 411 | if (i != AVB_MAX_NUMBER_OF_ROLLBACK_INDEX_LOCATIONS + 1) |
409 | strncat(buffer, ",", strlen(",")); | 412 | strncat(buffer, ",", strlen(",")); |
410 | 413 | ||
411 | if ((chars_left - (int)strlen(buffer)) >= 0) { | 414 | if ((chars_left - (int)strlen(buffer)) >= 0) { |
412 | strncat(response, buffer, strlen(buffer)); | 415 | strncat(response, buffer, strlen(buffer)); |
413 | chars_left -= strlen(buffer); | 416 | chars_left -= strlen(buffer); |
414 | } else { | 417 | } else { |
415 | strncat(response, buffer, chars_left); | 418 | strncat(response, buffer, chars_left); |
416 | /* reponse buffer is full, send it first */ | 419 | /* reponse buffer is full, send it first */ |
417 | fastboot_tx_write_more(response); | 420 | fastboot_tx_write_more(response); |
418 | /* reset the reponse buffer for next round */ | 421 | /* reset the reponse buffer for next round */ |
419 | memset(response, '\0', FASTBOOT_RESPONSE_LEN); | 422 | memset(response, '\0', FASTBOOT_RESPONSE_LEN); |
420 | strncpy(response, "INFO", 5); | 423 | strncpy(response, "INFO", 5); |
421 | /* Copy left strings from 'buffer' to 'response' */ | 424 | /* Copy left strings from 'buffer' to 'response' */ |
422 | strncat(response, buffer + chars_left, strlen(buffer)); | 425 | strncat(response, buffer + chars_left, strlen(buffer)); |
423 | chars_left = FASTBOOT_RESPONSE_LEN - | 426 | chars_left = FASTBOOT_RESPONSE_LEN - |
424 | strlen(response) - 1; | 427 | strlen(response) - 1; |
425 | } | 428 | } |
426 | } | 429 | } |
427 | 430 | ||
428 | } | 431 | } |
429 | #endif | 432 | #endif |
430 | else { | 433 | else { |
431 | char envstr[32]; | 434 | char envstr[32]; |
432 | 435 | ||
433 | snprintf(envstr, sizeof(envstr) - 1, "fastboot.%s", cmd); | 436 | snprintf(envstr, sizeof(envstr) - 1, "fastboot.%s", cmd); |
434 | s = env_get(envstr); | 437 | s = env_get(envstr); |
435 | if (s) { | 438 | if (s) { |
436 | strncat(response, s, chars_left); | 439 | strncat(response, s, chars_left); |
437 | } else { | 440 | } else { |
438 | snprintf(response, chars_left, "FAILunknown variable:%s",cmd); | 441 | snprintf(response, chars_left, "FAILunknown variable:%s",cmd); |
439 | printf("WARNING: unknown variable: %s\n", cmd); | 442 | printf("WARNING: unknown variable: %s\n", cmd); |
440 | return -1; | 443 | return -1; |
441 | } | 444 | } |
442 | } | 445 | } |
443 | return 0; | 446 | return 0; |
444 | } | 447 | } |
445 | 448 | ||
446 | void fastboot_getvar(char *cmd, char *response) | 449 | void fastboot_getvar(char *cmd, char *response) |
447 | { | 450 | { |
448 | int n = 0; | 451 | int n = 0; |
449 | int status = 0; | 452 | int status = 0; |
450 | int count = 0; | 453 | int count = 0; |
451 | char var_name[FASTBOOT_RESPONSE_LEN]; | 454 | char var_name[FASTBOOT_RESPONSE_LEN]; |
452 | char partition_base_name[MAX_PTN][16]; | 455 | char partition_base_name[MAX_PTN][16]; |
453 | char slot_suffix[2][5] = {"a","b"}; | 456 | char slot_suffix[2][5] = {"a","b"}; |
454 | 457 | ||
455 | if (!cmd) { | 458 | if (!cmd) { |
456 | pr_err("missing variable"); | 459 | pr_err("missing variable"); |
457 | fastboot_fail("missing var", response); | 460 | fastboot_fail("missing var", response); |
458 | return; | 461 | return; |
459 | } | 462 | } |
460 | 463 | ||
461 | if (!strcmp_l1("all", cmd)) { | 464 | if (!strcmp_l1("all", cmd)) { |
462 | 465 | ||
463 | memset(response, '\0', FASTBOOT_RESPONSE_LEN); | 466 | memset(response, '\0', FASTBOOT_RESPONSE_LEN); |
464 | 467 | ||
465 | 468 | ||
466 | /* get common variables */ | 469 | /* get common variables */ |
467 | for (n = 0; n < FASTBOOT_COMMON_VAR_NUM; n++) { | 470 | for (n = 0; n < FASTBOOT_COMMON_VAR_NUM; n++) { |
468 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_common_var[n]); | 471 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_common_var[n]); |
469 | get_single_var(fastboot_common_var[n], response); | 472 | get_single_var(fastboot_common_var[n], response); |
470 | fastboot_tx_write_more(response); | 473 | fastboot_tx_write_more(response); |
471 | } | 474 | } |
472 | 475 | ||
473 | /* get at-vboot-state variables */ | 476 | /* get at-vboot-state variables */ |
474 | #ifdef CONFIG_AVB_ATX | 477 | #ifdef CONFIG_AVB_ATX |
475 | for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) { | 478 | for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) { |
476 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_at_vboot_state_var[n]); | 479 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_at_vboot_state_var[n]); |
477 | get_single_var(fastboot_at_vboot_state_var[n], response); | 480 | get_single_var(fastboot_at_vboot_state_var[n], response); |
478 | fastboot_tx_write_more(response); | 481 | fastboot_tx_write_more(response); |
479 | } | 482 | } |
480 | #endif | 483 | #endif |
481 | /* get partition type */ | 484 | /* get partition type */ |
482 | for (n = 0; n < g_pcount; n++) { | 485 | for (n = 0; n < g_pcount; n++) { |
483 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOpartition-type:%s:", g_ptable[n].name); | 486 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOpartition-type:%s:", g_ptable[n].name); |
484 | snprintf(var_name, sizeof(var_name), "partition-type:%s", g_ptable[n].name); | 487 | snprintf(var_name, sizeof(var_name), "partition-type:%s", g_ptable[n].name); |
485 | get_single_var(var_name, response); | 488 | get_single_var(var_name, response); |
486 | fastboot_tx_write_more(response); | 489 | fastboot_tx_write_more(response); |
487 | } | 490 | } |
488 | /* get partition size */ | 491 | /* get partition size */ |
489 | for (n = 0; n < g_pcount; n++) { | 492 | for (n = 0; n < g_pcount; n++) { |
490 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOpartition-size:%s:", g_ptable[n].name); | 493 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOpartition-size:%s:", g_ptable[n].name); |
491 | snprintf(var_name, sizeof(var_name), "partition-size:%s", g_ptable[n].name); | 494 | snprintf(var_name, sizeof(var_name), "partition-size:%s", g_ptable[n].name); |
492 | get_single_var(var_name,response); | 495 | get_single_var(var_name,response); |
493 | fastboot_tx_write_more(response); | 496 | fastboot_tx_write_more(response); |
494 | } | 497 | } |
495 | /* slot related variables */ | 498 | /* slot related variables */ |
496 | if (fastboot_parts_is_slot()) { | 499 | if (fastboot_parts_is_slot()) { |
497 | /* get has-slot variables */ | 500 | /* get has-slot variables */ |
498 | count = fastboot_parts_get_name(partition_base_name); | 501 | count = fastboot_parts_get_name(partition_base_name); |
499 | for (n = 0; n < count; n++) { | 502 | for (n = 0; n < count; n++) { |
500 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOhas-slot:%s:", partition_base_name[n]); | 503 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOhas-slot:%s:", partition_base_name[n]); |
501 | snprintf(var_name, sizeof(var_name), "has-slot:%s", partition_base_name[n]); | 504 | snprintf(var_name, sizeof(var_name), "has-slot:%s", partition_base_name[n]); |
502 | get_single_var(var_name,response); | 505 | get_single_var(var_name,response); |
503 | fastboot_tx_write_more(response); | 506 | fastboot_tx_write_more(response); |
504 | } | 507 | } |
505 | /* get current slot */ | 508 | /* get current slot */ |
506 | strncpy(response, "INFOcurrent-slot:", FASTBOOT_RESPONSE_LEN); | 509 | strncpy(response, "INFOcurrent-slot:", FASTBOOT_RESPONSE_LEN); |
507 | get_single_var("current-slot", response); | 510 | get_single_var("current-slot", response); |
508 | fastboot_tx_write_more(response); | 511 | fastboot_tx_write_more(response); |
509 | /* get slot count */ | 512 | /* get slot count */ |
510 | strncpy(response, "INFOslot-count:", FASTBOOT_RESPONSE_LEN); | 513 | strncpy(response, "INFOslot-count:", FASTBOOT_RESPONSE_LEN); |
511 | get_single_var("slot-count", response); | 514 | get_single_var("slot-count", response); |
512 | fastboot_tx_write_more(response); | 515 | fastboot_tx_write_more(response); |
513 | /* get slot-successful variable */ | 516 | /* get slot-successful variable */ |
514 | for (n = 0; n < 2; n++) { | 517 | for (n = 0; n < 2; n++) { |
515 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-successful:%s:", slot_suffix[n]); | 518 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-successful:%s:", slot_suffix[n]); |
516 | snprintf(var_name, sizeof(var_name), "slot-successful:%s", slot_suffix[n]); | 519 | snprintf(var_name, sizeof(var_name), "slot-successful:%s", slot_suffix[n]); |
517 | get_single_var(var_name, response); | 520 | get_single_var(var_name, response); |
518 | fastboot_tx_write_more(response); | 521 | fastboot_tx_write_more(response); |
519 | } | 522 | } |
520 | /*get slot-unbootable variable*/ | 523 | /*get slot-unbootable variable*/ |
521 | for (n = 0; n < 2; n++) { | 524 | for (n = 0; n < 2; n++) { |
522 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-unbootable:%s:", slot_suffix[n]); | 525 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-unbootable:%s:", slot_suffix[n]); |
523 | snprintf(var_name, sizeof(var_name), "slot-unbootable:%s", slot_suffix[n]); | 526 | snprintf(var_name, sizeof(var_name), "slot-unbootable:%s", slot_suffix[n]); |
524 | get_single_var(var_name, response); | 527 | get_single_var(var_name, response); |
525 | fastboot_tx_write_more(response); | 528 | fastboot_tx_write_more(response); |
526 | } | 529 | } |
527 | /*get slot-retry-count variable*/ | 530 | /*get slot-retry-count variable*/ |
528 | for (n = 0; n < 2; n++) { | 531 | for (n = 0; n < 2; n++) { |
529 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-retry-count:%s:", slot_suffix[n]); | 532 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFOslot-retry-count:%s:", slot_suffix[n]); |
530 | snprintf(var_name, sizeof(var_name), "slot-retry-count:%s", slot_suffix[n]); | 533 | snprintf(var_name, sizeof(var_name), "slot-retry-count:%s", slot_suffix[n]); |
531 | get_single_var(var_name, response); | 534 | get_single_var(var_name, response); |
532 | fastboot_tx_write_more(response); | 535 | fastboot_tx_write_more(response); |
533 | } | 536 | } |
534 | } | 537 | } |
535 | 538 | ||
536 | strncpy(response, "OKAYDone!", 10); | 539 | strncpy(response, "OKAYDone!", 10); |
537 | fastboot_tx_write_more(response); | 540 | fastboot_tx_write_more(response); |
538 | fastboot_none_resp(response); | 541 | fastboot_none_resp(response); |
539 | 542 | ||
540 | return; | 543 | return; |
541 | } | 544 | } |
542 | #ifdef CONFIG_AVB_ATX | 545 | #ifdef CONFIG_AVB_ATX |
543 | else if (!strcmp_l1("at-vboot-state", cmd)) { | 546 | else if (!strcmp_l1("at-vboot-state", cmd)) { |
544 | /* get at-vboot-state variables */ | 547 | /* get at-vboot-state variables */ |
545 | for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) { | 548 | for (n = 0; n < AT_VBOOT_STATE_VAR_NUM; n++) { |
546 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_at_vboot_state_var[n]); | 549 | snprintf(response, FASTBOOT_RESPONSE_LEN, "INFO%s:", fastboot_at_vboot_state_var[n]); |
547 | get_single_var(fastboot_at_vboot_state_var[n], response); | 550 | get_single_var(fastboot_at_vboot_state_var[n], response); |
548 | fastboot_tx_write_more(response); | 551 | fastboot_tx_write_more(response); |
549 | } | 552 | } |
550 | 553 | ||
551 | strncpy(response, "OKAY", 5); | 554 | strncpy(response, "OKAY", 5); |
552 | fastboot_tx_write_more(response); | 555 | fastboot_tx_write_more(response); |
553 | fastboot_none_resp(response); | 556 | fastboot_none_resp(response); |
554 | 557 | ||
555 | return; | 558 | return; |
556 | } else if ((!strcmp_l1("bootloader-locked", cmd)) || | 559 | } else if ((!strcmp_l1("bootloader-locked", cmd)) || |
557 | (!strcmp_l1("bootloader-min-versions", cmd)) || | 560 | (!strcmp_l1("bootloader-min-versions", cmd)) || |
558 | (!strcmp_l1("avb-perm-attr-set", cmd)) || | 561 | (!strcmp_l1("avb-perm-attr-set", cmd)) || |
559 | (!strcmp_l1("avb-locked", cmd)) || | 562 | (!strcmp_l1("avb-locked", cmd)) || |
560 | (!strcmp_l1("avb-unlock-disabled", cmd)) || | 563 | (!strcmp_l1("avb-unlock-disabled", cmd)) || |
561 | (!strcmp_l1("avb-min-versions", cmd))) { | 564 | (!strcmp_l1("avb-min-versions", cmd))) { |
562 | 565 | ||
563 | printf("Can't get this variable alone, get 'at-vboot-state' instead!\n"); | 566 | printf("Can't get this variable alone, get 'at-vboot-state' instead!\n"); |
564 | fastboot_fail("Can't get this variable alone, get 'at-vboot-state' instead.", response); | 567 | fastboot_fail("Can't get this variable alone, get 'at-vboot-state' instead.", response); |
565 | return; | 568 | return; |
566 | } | 569 | } |
567 | #endif | 570 | #endif |
568 | else { | 571 | else { |
569 | char reason[FASTBOOT_RESPONSE_LEN]; | 572 | char reason[FASTBOOT_RESPONSE_LEN]; |
570 | memset(reason, '\0', FASTBOOT_RESPONSE_LEN); | 573 | memset(reason, '\0', FASTBOOT_RESPONSE_LEN); |
571 | 574 | ||
572 | status = get_single_var(cmd, reason); | 575 | status = get_single_var(cmd, reason); |
573 | if (status != 0) | 576 | if (status != 0) |
574 | fastboot_fail(reason, response); | 577 | fastboot_fail(reason, response); |
575 | else | 578 | else |
576 | fastboot_okay(reason, response); | 579 | fastboot_okay(reason, response); |
577 | 580 | ||
578 | return; | 581 | return; |
579 | } | 582 | } |
580 | } | 583 | } |
581 | 584 |
drivers/usb/gadget/f_fastboot.c
1 | // SPDX-License-Identifier: GPL-2.0+ | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | 2 | /* |
3 | * (C) Copyright 2008 - 2009 | 3 | * (C) Copyright 2008 - 2009 |
4 | * Windriver, <www.windriver.com> | 4 | * Windriver, <www.windriver.com> |
5 | * Tom Rix <Tom.Rix@windriver.com> | 5 | * Tom Rix <Tom.Rix@windriver.com> |
6 | * | 6 | * |
7 | * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 7 | * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
8 | * | 8 | * |
9 | * Copyright 2014 Linaro, Ltd. | 9 | * Copyright 2014 Linaro, Ltd. |
10 | * Rob Herring <robh@kernel.org> | 10 | * Rob Herring <robh@kernel.org> |
11 | */ | 11 | */ |
12 | #include <config.h> | 12 | #include <config.h> |
13 | #include <common.h> | 13 | #include <common.h> |
14 | #include <env.h> | 14 | #include <env.h> |
15 | #include <errno.h> | 15 | #include <errno.h> |
16 | #include <fastboot.h> | 16 | #include <fastboot.h> |
17 | #include <malloc.h> | 17 | #include <malloc.h> |
18 | #include <linux/usb/ch9.h> | 18 | #include <linux/usb/ch9.h> |
19 | #include <linux/usb/gadget.h> | 19 | #include <linux/usb/gadget.h> |
20 | #include <linux/usb/composite.h> | 20 | #include <linux/usb/composite.h> |
21 | #include <linux/compiler.h> | 21 | #include <linux/compiler.h> |
22 | #include <g_dnl.h> | 22 | #include <g_dnl.h> |
23 | #include <serial.h> | 23 | #include <serial.h> |
24 | #include <stdio_dev.h> | 24 | #include <stdio_dev.h> |
25 | 25 | ||
26 | #define FASTBOOT_INTERFACE_CLASS 0xff | 26 | #define FASTBOOT_INTERFACE_CLASS 0xff |
27 | #define FASTBOOT_INTERFACE_SUB_CLASS 0x42 | 27 | #define FASTBOOT_INTERFACE_SUB_CLASS 0x42 |
28 | #define FASTBOOT_INTERFACE_PROTOCOL 0x03 | 28 | #define FASTBOOT_INTERFACE_PROTOCOL 0x03 |
29 | 29 | ||
30 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200) | 30 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200) |
31 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1 (0x0040) | 31 | #define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1 (0x0040) |
32 | #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040) | 32 | #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040) |
33 | 33 | ||
34 | #define EP_BUFFER_SIZE 4096 | 34 | #define EP_BUFFER_SIZE 4096 |
35 | /* | 35 | /* |
36 | * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size | 36 | * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size |
37 | * (64 or 512 or 1024), else we break on certain controllers like DWC3 | 37 | * (64 or 512 or 1024), else we break on certain controllers like DWC3 |
38 | * that expect bulk OUT requests to be divisible by maxpacket size. | 38 | * that expect bulk OUT requests to be divisible by maxpacket size. |
39 | */ | 39 | */ |
40 | 40 | ||
41 | typedef struct usb_req usb_req; | 41 | typedef struct usb_req usb_req; |
42 | struct usb_req { | 42 | struct usb_req { |
43 | struct usb_request *in_req; | 43 | struct usb_request *in_req; |
44 | usb_req *next; | 44 | usb_req *next; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | struct f_fastboot { | 47 | struct f_fastboot { |
48 | struct usb_function usb_function; | 48 | struct usb_function usb_function; |
49 | 49 | ||
50 | /* IN/OUT EP's and corresponding requests */ | 50 | /* IN/OUT EP's and corresponding requests */ |
51 | struct usb_ep *in_ep, *out_ep; | 51 | struct usb_ep *in_ep, *out_ep; |
52 | struct usb_request *in_req, *out_req; | 52 | struct usb_request *in_req, *out_req; |
53 | 53 | ||
54 | usb_req *front, *rear; | 54 | usb_req *front, *rear; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static char fb_ext_prop_name[] = "DeviceInterfaceGUID"; | 57 | static char fb_ext_prop_name[] = "DeviceInterfaceGUID"; |
58 | static char fb_ext_prop_data[] = "{4866319A-F4D6-4374-93B9-DC2DEB361BA9}"; | 58 | static char fb_ext_prop_data[] = "{4866319A-F4D6-4374-93B9-DC2DEB361BA9}"; |
59 | 59 | ||
60 | static struct usb_os_desc_ext_prop fb_ext_prop = { | 60 | static struct usb_os_desc_ext_prop fb_ext_prop = { |
61 | .type = 1, /* NUL-terminated Unicode String (REG_SZ) */ | 61 | .type = 1, /* NUL-terminated Unicode String (REG_SZ) */ |
62 | .name = fb_ext_prop_name, | 62 | .name = fb_ext_prop_name, |
63 | .data = fb_ext_prop_data, | 63 | .data = fb_ext_prop_data, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | /* 16 bytes of "Compatible ID" and "Subcompatible ID" */ | 66 | /* 16 bytes of "Compatible ID" and "Subcompatible ID" */ |
67 | static char fb_cid[16] = {'W', 'I', 'N', 'U', 'S', 'B'}; | 67 | static char fb_cid[16] = {'W', 'I', 'N', 'U', 'S', 'B'}; |
68 | static struct usb_os_desc fb_os_desc = { | 68 | static struct usb_os_desc fb_os_desc = { |
69 | .ext_compat_id = fb_cid, | 69 | .ext_compat_id = fb_cid, |
70 | }; | 70 | }; |
71 | 71 | ||
72 | static struct usb_os_desc_table fb_os_desc_table = { | 72 | static struct usb_os_desc_table fb_os_desc_table = { |
73 | .os_desc = &fb_os_desc, | 73 | .os_desc = &fb_os_desc, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | static inline struct f_fastboot *func_to_fastboot(struct usb_function *f) | 76 | static inline struct f_fastboot *func_to_fastboot(struct usb_function *f) |
77 | { | 77 | { |
78 | return container_of(f, struct f_fastboot, usb_function); | 78 | return container_of(f, struct f_fastboot, usb_function); |
79 | } | 79 | } |
80 | 80 | ||
81 | static struct f_fastboot *fastboot_func; | 81 | static struct f_fastboot *fastboot_func; |
82 | 82 | ||
83 | static struct usb_endpoint_descriptor fs_ep_in = { | 83 | static struct usb_endpoint_descriptor fs_ep_in = { |
84 | .bLength = USB_DT_ENDPOINT_SIZE, | 84 | .bLength = USB_DT_ENDPOINT_SIZE, |
85 | .bDescriptorType = USB_DT_ENDPOINT, | 85 | .bDescriptorType = USB_DT_ENDPOINT, |
86 | .bEndpointAddress = USB_DIR_IN, | 86 | .bEndpointAddress = USB_DIR_IN, |
87 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 87 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
88 | .wMaxPacketSize = cpu_to_le16(64), | 88 | .wMaxPacketSize = cpu_to_le16(64), |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static struct usb_endpoint_descriptor fs_ep_out = { | 91 | static struct usb_endpoint_descriptor fs_ep_out = { |
92 | .bLength = USB_DT_ENDPOINT_SIZE, | 92 | .bLength = USB_DT_ENDPOINT_SIZE, |
93 | .bDescriptorType = USB_DT_ENDPOINT, | 93 | .bDescriptorType = USB_DT_ENDPOINT, |
94 | .bEndpointAddress = USB_DIR_OUT, | 94 | .bEndpointAddress = USB_DIR_OUT, |
95 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 95 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
96 | .wMaxPacketSize = cpu_to_le16(64), | 96 | .wMaxPacketSize = cpu_to_le16(64), |
97 | }; | 97 | }; |
98 | 98 | ||
99 | static struct usb_endpoint_descriptor hs_ep_in = { | 99 | static struct usb_endpoint_descriptor hs_ep_in = { |
100 | .bLength = USB_DT_ENDPOINT_SIZE, | 100 | .bLength = USB_DT_ENDPOINT_SIZE, |
101 | .bDescriptorType = USB_DT_ENDPOINT, | 101 | .bDescriptorType = USB_DT_ENDPOINT, |
102 | .bEndpointAddress = USB_DIR_IN, | 102 | .bEndpointAddress = USB_DIR_IN, |
103 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 103 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
104 | .wMaxPacketSize = cpu_to_le16(512), | 104 | .wMaxPacketSize = cpu_to_le16(512), |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static struct usb_endpoint_descriptor hs_ep_out = { | 107 | static struct usb_endpoint_descriptor hs_ep_out = { |
108 | .bLength = USB_DT_ENDPOINT_SIZE, | 108 | .bLength = USB_DT_ENDPOINT_SIZE, |
109 | .bDescriptorType = USB_DT_ENDPOINT, | 109 | .bDescriptorType = USB_DT_ENDPOINT, |
110 | .bEndpointAddress = USB_DIR_OUT, | 110 | .bEndpointAddress = USB_DIR_OUT, |
111 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 111 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
112 | .wMaxPacketSize = cpu_to_le16(512), | 112 | .wMaxPacketSize = cpu_to_le16(512), |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static struct usb_interface_descriptor interface_desc = { | 115 | static struct usb_interface_descriptor interface_desc = { |
116 | .bLength = USB_DT_INTERFACE_SIZE, | 116 | .bLength = USB_DT_INTERFACE_SIZE, |
117 | .bDescriptorType = USB_DT_INTERFACE, | 117 | .bDescriptorType = USB_DT_INTERFACE, |
118 | .bInterfaceNumber = 0x00, | 118 | .bInterfaceNumber = 0x00, |
119 | .bAlternateSetting = 0x00, | 119 | .bAlternateSetting = 0x00, |
120 | .bNumEndpoints = 0x02, | 120 | .bNumEndpoints = 0x02, |
121 | .bInterfaceClass = FASTBOOT_INTERFACE_CLASS, | 121 | .bInterfaceClass = FASTBOOT_INTERFACE_CLASS, |
122 | .bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS, | 122 | .bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS, |
123 | .bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL, | 123 | .bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL, |
124 | }; | 124 | }; |
125 | 125 | ||
126 | static struct usb_descriptor_header *fb_fs_function[] = { | 126 | static struct usb_descriptor_header *fb_fs_function[] = { |
127 | (struct usb_descriptor_header *)&interface_desc, | 127 | (struct usb_descriptor_header *)&interface_desc, |
128 | (struct usb_descriptor_header *)&fs_ep_in, | 128 | (struct usb_descriptor_header *)&fs_ep_in, |
129 | (struct usb_descriptor_header *)&fs_ep_out, | 129 | (struct usb_descriptor_header *)&fs_ep_out, |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static struct usb_descriptor_header *fb_hs_function[] = { | 132 | static struct usb_descriptor_header *fb_hs_function[] = { |
133 | (struct usb_descriptor_header *)&interface_desc, | 133 | (struct usb_descriptor_header *)&interface_desc, |
134 | (struct usb_descriptor_header *)&hs_ep_in, | 134 | (struct usb_descriptor_header *)&hs_ep_in, |
135 | (struct usb_descriptor_header *)&hs_ep_out, | 135 | (struct usb_descriptor_header *)&hs_ep_out, |
136 | NULL, | 136 | NULL, |
137 | }; | 137 | }; |
138 | 138 | ||
139 | /* Super speed */ | 139 | /* Super speed */ |
140 | static struct usb_endpoint_descriptor ss_ep_in = { | 140 | static struct usb_endpoint_descriptor ss_ep_in = { |
141 | .bLength = USB_DT_ENDPOINT_SIZE, | 141 | .bLength = USB_DT_ENDPOINT_SIZE, |
142 | .bDescriptorType = USB_DT_ENDPOINT, | 142 | .bDescriptorType = USB_DT_ENDPOINT, |
143 | .bEndpointAddress = USB_DIR_IN, | 143 | .bEndpointAddress = USB_DIR_IN, |
144 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 144 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
145 | .wMaxPacketSize = cpu_to_le16(1024), | 145 | .wMaxPacketSize = cpu_to_le16(1024), |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static struct usb_endpoint_descriptor ss_ep_out = { | 148 | static struct usb_endpoint_descriptor ss_ep_out = { |
149 | .bLength = USB_DT_ENDPOINT_SIZE, | 149 | .bLength = USB_DT_ENDPOINT_SIZE, |
150 | .bDescriptorType = USB_DT_ENDPOINT, | 150 | .bDescriptorType = USB_DT_ENDPOINT, |
151 | .bEndpointAddress = USB_DIR_OUT, | 151 | .bEndpointAddress = USB_DIR_OUT, |
152 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 152 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
153 | .wMaxPacketSize = cpu_to_le16(1024), | 153 | .wMaxPacketSize = cpu_to_le16(1024), |
154 | }; | 154 | }; |
155 | 155 | ||
156 | static struct usb_ss_ep_comp_descriptor fb_ss_bulk_comp_desc = { | 156 | static struct usb_ss_ep_comp_descriptor fb_ss_bulk_comp_desc = { |
157 | .bLength = sizeof(fb_ss_bulk_comp_desc), | 157 | .bLength = sizeof(fb_ss_bulk_comp_desc), |
158 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 158 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
159 | }; | 159 | }; |
160 | 160 | ||
161 | static struct usb_descriptor_header *fb_ss_function[] = { | 161 | static struct usb_descriptor_header *fb_ss_function[] = { |
162 | (struct usb_descriptor_header *)&interface_desc, | 162 | (struct usb_descriptor_header *)&interface_desc, |
163 | (struct usb_descriptor_header *)&ss_ep_in, | 163 | (struct usb_descriptor_header *)&ss_ep_in, |
164 | (struct usb_descriptor_header *)&fb_ss_bulk_comp_desc, | 164 | (struct usb_descriptor_header *)&fb_ss_bulk_comp_desc, |
165 | (struct usb_descriptor_header *)&ss_ep_out, | 165 | (struct usb_descriptor_header *)&ss_ep_out, |
166 | (struct usb_descriptor_header *)&fb_ss_bulk_comp_desc, | 166 | (struct usb_descriptor_header *)&fb_ss_bulk_comp_desc, |
167 | NULL, | 167 | NULL, |
168 | }; | 168 | }; |
169 | 169 | ||
170 | static struct usb_endpoint_descriptor * | 170 | static struct usb_endpoint_descriptor * |
171 | fb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, | 171 | fb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, |
172 | struct usb_endpoint_descriptor *hs, | 172 | struct usb_endpoint_descriptor *hs, |
173 | struct usb_endpoint_descriptor *ss) | 173 | struct usb_endpoint_descriptor *ss) |
174 | { | 174 | { |
175 | if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER) | 175 | if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER) |
176 | return ss; | 176 | return ss; |
177 | 177 | ||
178 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | 178 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) |
179 | return hs; | 179 | return hs; |
180 | return fs; | 180 | return fs; |
181 | } | 181 | } |
182 | 182 | ||
183 | /* | 183 | /* |
184 | * static strings, in UTF-8 | 184 | * static strings, in UTF-8 |
185 | */ | 185 | */ |
186 | static const char fastboot_name[] = "Android Fastboot"; | 186 | static const char fastboot_name[] = "Android Fastboot"; |
187 | 187 | ||
188 | static struct usb_string fastboot_string_defs[] = { | 188 | static struct usb_string fastboot_string_defs[] = { |
189 | [0].s = fastboot_name, | 189 | [0].s = fastboot_name, |
190 | { } /* end of list */ | 190 | { } /* end of list */ |
191 | }; | 191 | }; |
192 | 192 | ||
193 | static struct usb_gadget_strings stringtab_fastboot = { | 193 | static struct usb_gadget_strings stringtab_fastboot = { |
194 | .language = 0x0409, /* en-us */ | 194 | .language = 0x0409, /* en-us */ |
195 | .strings = fastboot_string_defs, | 195 | .strings = fastboot_string_defs, |
196 | }; | 196 | }; |
197 | 197 | ||
198 | static struct usb_gadget_strings *fastboot_strings[] = { | 198 | static struct usb_gadget_strings *fastboot_strings[] = { |
199 | &stringtab_fastboot, | 199 | &stringtab_fastboot, |
200 | NULL, | 200 | NULL, |
201 | }; | 201 | }; |
202 | 202 | ||
203 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 203 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
204 | extern struct stdio_dev g_fastboot_stdio; | 204 | extern struct stdio_dev g_fastboot_stdio; |
205 | #endif | 205 | #endif |
206 | 206 | ||
207 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); | 207 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); |
208 | 208 | ||
209 | static void fastboot_fifo_complete(struct usb_ep *ep, struct usb_request *req) | 209 | static void fastboot_fifo_complete(struct usb_ep *ep, struct usb_request *req) |
210 | { | 210 | { |
211 | int status = req->status; | 211 | int status = req->status; |
212 | usb_req *request; | 212 | usb_req *request; |
213 | 213 | ||
214 | if (!status) { | 214 | if (!status) { |
215 | if (fastboot_func->front != NULL) { | 215 | if (fastboot_func->front != NULL) { |
216 | request = fastboot_func->front; | 216 | request = fastboot_func->front; |
217 | fastboot_func->front = fastboot_func->front->next; | 217 | fastboot_func->front = fastboot_func->front->next; |
218 | usb_ep_free_request(ep, request->in_req); | 218 | usb_ep_free_request(ep, request->in_req); |
219 | free(request); | 219 | free(request); |
220 | } else { | 220 | } else { |
221 | printf("fail free request\n"); | 221 | printf("fail free request\n"); |
222 | } | 222 | } |
223 | return; | 223 | return; |
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) | 227 | static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) |
228 | { | 228 | { |
229 | int status = req->status; | 229 | int status = req->status; |
230 | if (!status) | 230 | if (!status) |
231 | return; | 231 | return; |
232 | printf("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual); | 232 | printf("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual); |
233 | } | 233 | } |
234 | 234 | ||
235 | static int fastboot_bind(struct usb_configuration *c, struct usb_function *f) | 235 | static int fastboot_bind(struct usb_configuration *c, struct usb_function *f) |
236 | { | 236 | { |
237 | int id; | 237 | int id; |
238 | struct usb_gadget *gadget = c->cdev->gadget; | 238 | struct usb_gadget *gadget = c->cdev->gadget; |
239 | struct f_fastboot *f_fb = func_to_fastboot(f); | 239 | struct f_fastboot *f_fb = func_to_fastboot(f); |
240 | const char *s; | 240 | const char *s; |
241 | 241 | ||
242 | /* DYNAMIC interface numbers assignments */ | 242 | /* DYNAMIC interface numbers assignments */ |
243 | id = usb_interface_id(c, f); | 243 | id = usb_interface_id(c, f); |
244 | if (id < 0) | 244 | if (id < 0) |
245 | return id; | 245 | return id; |
246 | interface_desc.bInterfaceNumber = id; | 246 | interface_desc.bInterfaceNumber = id; |
247 | 247 | ||
248 | /* Enable OS and Extended Properties Feature Descriptor */ | 248 | /* Enable OS and Extended Properties Feature Descriptor */ |
249 | c->cdev->use_os_string = 1; | 249 | c->cdev->use_os_string = 1; |
250 | f->os_desc_table = &fb_os_desc_table; | 250 | f->os_desc_table = &fb_os_desc_table; |
251 | f->os_desc_n = 1; | 251 | f->os_desc_n = 1; |
252 | f->os_desc_table->if_id = id; | 252 | f->os_desc_table->if_id = id; |
253 | INIT_LIST_HEAD(&fb_os_desc.ext_prop); | 253 | INIT_LIST_HEAD(&fb_os_desc.ext_prop); |
254 | fb_ext_prop.name_len = strlen(fb_ext_prop.name) * 2 + 2; | 254 | fb_ext_prop.name_len = strlen(fb_ext_prop.name) * 2 + 2; |
255 | fb_os_desc.ext_prop_len = 10 + fb_ext_prop.name_len; | 255 | fb_os_desc.ext_prop_len = 10 + fb_ext_prop.name_len; |
256 | fb_os_desc.ext_prop_count = 1; | 256 | fb_os_desc.ext_prop_count = 1; |
257 | fb_ext_prop.data_len = strlen(fb_ext_prop.data) * 2 + 2; | 257 | fb_ext_prop.data_len = strlen(fb_ext_prop.data) * 2 + 2; |
258 | fb_os_desc.ext_prop_len += fb_ext_prop.data_len + 4; | 258 | fb_os_desc.ext_prop_len += fb_ext_prop.data_len + 4; |
259 | list_add_tail(&fb_ext_prop.entry, &fb_os_desc.ext_prop); | 259 | list_add_tail(&fb_ext_prop.entry, &fb_os_desc.ext_prop); |
260 | 260 | ||
261 | id = usb_string_id(c->cdev); | 261 | id = usb_string_id(c->cdev); |
262 | if (id < 0) | 262 | if (id < 0) |
263 | return id; | 263 | return id; |
264 | fastboot_string_defs[0].id = id; | 264 | fastboot_string_defs[0].id = id; |
265 | interface_desc.iInterface = id; | 265 | interface_desc.iInterface = id; |
266 | 266 | ||
267 | f_fb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in); | 267 | f_fb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in); |
268 | if (!f_fb->in_ep) | 268 | if (!f_fb->in_ep) |
269 | return -ENODEV; | 269 | return -ENODEV; |
270 | f_fb->in_ep->driver_data = c->cdev; | 270 | f_fb->in_ep->driver_data = c->cdev; |
271 | 271 | ||
272 | f_fb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out); | 272 | f_fb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out); |
273 | if (!f_fb->out_ep) | 273 | if (!f_fb->out_ep) |
274 | return -ENODEV; | 274 | return -ENODEV; |
275 | f_fb->out_ep->driver_data = c->cdev; | 275 | f_fb->out_ep->driver_data = c->cdev; |
276 | 276 | ||
277 | f->descriptors = fb_fs_function; | 277 | f->descriptors = fb_fs_function; |
278 | 278 | ||
279 | if (gadget_is_dualspeed(gadget)) { | 279 | if (gadget_is_dualspeed(gadget)) { |
280 | /* Assume endpoint addresses are the same for both speeds */ | 280 | /* Assume endpoint addresses are the same for both speeds */ |
281 | hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress; | 281 | hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress; |
282 | hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; | 282 | hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; |
283 | /* copy HS descriptors */ | 283 | /* copy HS descriptors */ |
284 | f->hs_descriptors = fb_hs_function; | 284 | f->hs_descriptors = fb_hs_function; |
285 | } | 285 | } |
286 | 286 | ||
287 | if (gadget_is_superspeed(gadget)) { | 287 | if (gadget_is_superspeed(gadget)) { |
288 | ss_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress; | 288 | ss_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress; |
289 | ss_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; | 289 | ss_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; |
290 | f->ss_descriptors = fb_ss_function; | 290 | f->ss_descriptors = fb_ss_function; |
291 | } | 291 | } |
292 | 292 | ||
293 | s = env_get("serial#"); | 293 | s = env_get("serial#"); |
294 | if (s) | 294 | if (s) |
295 | g_dnl_set_serialnumber((char *)s); | 295 | g_dnl_set_serialnumber((char *)s); |
296 | 296 | ||
297 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 297 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
298 | stdio_register(&g_fastboot_stdio); | 298 | stdio_register(&g_fastboot_stdio); |
299 | #endif | 299 | #endif |
300 | 300 | ||
301 | return 0; | 301 | return 0; |
302 | } | 302 | } |
303 | 303 | ||
304 | static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f) | 304 | static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f) |
305 | { | 305 | { |
306 | f->os_desc_table = NULL; | 306 | f->os_desc_table = NULL; |
307 | list_del(&fb_os_desc.ext_prop); | 307 | list_del(&fb_os_desc.ext_prop); |
308 | memset(fastboot_func, 0, sizeof(*fastboot_func)); | 308 | memset(fastboot_func, 0, sizeof(*fastboot_func)); |
309 | 309 | ||
310 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) && CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) | 310 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) && CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) |
311 | stdio_deregister("fastboot", 1); | 311 | stdio_deregister("fastboot", 1); |
312 | #endif | 312 | #endif |
313 | 313 | ||
314 | } | 314 | } |
315 | 315 | ||
316 | static void fastboot_disable(struct usb_function *f) | 316 | static void fastboot_disable(struct usb_function *f) |
317 | { | 317 | { |
318 | struct f_fastboot *f_fb = func_to_fastboot(f); | 318 | struct f_fastboot *f_fb = func_to_fastboot(f); |
319 | 319 | ||
320 | usb_ep_disable(f_fb->out_ep); | 320 | usb_ep_disable(f_fb->out_ep); |
321 | usb_ep_disable(f_fb->in_ep); | 321 | usb_ep_disable(f_fb->in_ep); |
322 | 322 | ||
323 | if (f_fb->out_req) { | 323 | if (f_fb->out_req) { |
324 | free(f_fb->out_req->buf); | 324 | free(f_fb->out_req->buf); |
325 | usb_ep_free_request(f_fb->out_ep, f_fb->out_req); | 325 | usb_ep_free_request(f_fb->out_ep, f_fb->out_req); |
326 | f_fb->out_req = NULL; | 326 | f_fb->out_req = NULL; |
327 | } | 327 | } |
328 | if (f_fb->in_req) { | 328 | if (f_fb->in_req) { |
329 | free(f_fb->in_req->buf); | 329 | free(f_fb->in_req->buf); |
330 | usb_ep_free_request(f_fb->in_ep, f_fb->in_req); | 330 | usb_ep_free_request(f_fb->in_ep, f_fb->in_req); |
331 | f_fb->in_req = NULL; | 331 | f_fb->in_req = NULL; |
332 | } | 332 | } |
333 | } | 333 | } |
334 | 334 | ||
335 | static struct usb_request *fastboot_start_ep(struct usb_ep *ep) | 335 | static struct usb_request *fastboot_start_ep(struct usb_ep *ep) |
336 | { | 336 | { |
337 | struct usb_request *req; | 337 | struct usb_request *req; |
338 | 338 | ||
339 | req = usb_ep_alloc_request(ep, 0); | 339 | req = usb_ep_alloc_request(ep, 0); |
340 | if (!req) | 340 | if (!req) |
341 | return NULL; | 341 | return NULL; |
342 | 342 | ||
343 | req->length = EP_BUFFER_SIZE; | 343 | req->length = EP_BUFFER_SIZE; |
344 | req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE); | 344 | req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE); |
345 | if (!req->buf) { | 345 | if (!req->buf) { |
346 | usb_ep_free_request(ep, req); | 346 | usb_ep_free_request(ep, req); |
347 | return NULL; | 347 | return NULL; |
348 | } | 348 | } |
349 | 349 | ||
350 | memset(req->buf, 0, req->length); | 350 | memset(req->buf, 0, req->length); |
351 | return req; | 351 | return req; |
352 | } | 352 | } |
353 | 353 | ||
354 | static int fastboot_set_alt(struct usb_function *f, | 354 | static int fastboot_set_alt(struct usb_function *f, |
355 | unsigned interface, unsigned alt) | 355 | unsigned interface, unsigned alt) |
356 | { | 356 | { |
357 | int ret; | 357 | int ret; |
358 | struct usb_composite_dev *cdev = f->config->cdev; | 358 | struct usb_composite_dev *cdev = f->config->cdev; |
359 | struct usb_gadget *gadget = cdev->gadget; | 359 | struct usb_gadget *gadget = cdev->gadget; |
360 | struct f_fastboot *f_fb = func_to_fastboot(f); | 360 | struct f_fastboot *f_fb = func_to_fastboot(f); |
361 | const struct usb_endpoint_descriptor *d; | 361 | const struct usb_endpoint_descriptor *d; |
362 | 362 | ||
363 | debug("%s: func: %s intf: %d alt: %d\n", | 363 | debug("%s: func: %s intf: %d alt: %d\n", |
364 | __func__, f->name, interface, alt); | 364 | __func__, f->name, interface, alt); |
365 | 365 | ||
366 | d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out, &ss_ep_out); | 366 | d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out, &ss_ep_out); |
367 | ret = usb_ep_enable(f_fb->out_ep, d); | 367 | ret = usb_ep_enable(f_fb->out_ep, d); |
368 | if (ret) { | 368 | if (ret) { |
369 | puts("failed to enable out ep\n"); | 369 | puts("failed to enable out ep\n"); |
370 | return ret; | 370 | return ret; |
371 | } | 371 | } |
372 | 372 | ||
373 | f_fb->out_req = fastboot_start_ep(f_fb->out_ep); | 373 | f_fb->out_req = fastboot_start_ep(f_fb->out_ep); |
374 | if (!f_fb->out_req) { | 374 | if (!f_fb->out_req) { |
375 | puts("failed to alloc out req\n"); | 375 | puts("failed to alloc out req\n"); |
376 | ret = -EINVAL; | 376 | ret = -EINVAL; |
377 | goto err; | 377 | goto err; |
378 | } | 378 | } |
379 | f_fb->out_req->complete = rx_handler_command; | 379 | f_fb->out_req->complete = rx_handler_command; |
380 | 380 | ||
381 | d = fb_ep_desc(gadget, &fs_ep_in, &hs_ep_in, &ss_ep_in); | 381 | d = fb_ep_desc(gadget, &fs_ep_in, &hs_ep_in, &ss_ep_in); |
382 | ret = usb_ep_enable(f_fb->in_ep, d); | 382 | ret = usb_ep_enable(f_fb->in_ep, d); |
383 | if (ret) { | 383 | if (ret) { |
384 | puts("failed to enable in ep\n"); | 384 | puts("failed to enable in ep\n"); |
385 | goto err; | 385 | goto err; |
386 | } | 386 | } |
387 | 387 | ||
388 | f_fb->in_req = fastboot_start_ep(f_fb->in_ep); | 388 | f_fb->in_req = fastboot_start_ep(f_fb->in_ep); |
389 | if (!f_fb->in_req) { | 389 | if (!f_fb->in_req) { |
390 | puts("failed alloc req in\n"); | 390 | puts("failed alloc req in\n"); |
391 | ret = -EINVAL; | 391 | ret = -EINVAL; |
392 | goto err; | 392 | goto err; |
393 | } | 393 | } |
394 | f_fb->in_req->complete = fastboot_complete; | 394 | f_fb->in_req->complete = fastboot_complete; |
395 | 395 | ||
396 | ret = usb_ep_queue(f_fb->out_ep, f_fb->out_req, 0); | 396 | ret = usb_ep_queue(f_fb->out_ep, f_fb->out_req, 0); |
397 | if (ret) | 397 | if (ret) |
398 | goto err; | 398 | goto err; |
399 | 399 | ||
400 | return 0; | 400 | return 0; |
401 | err: | 401 | err: |
402 | fastboot_disable(f); | 402 | fastboot_disable(f); |
403 | return ret; | 403 | return ret; |
404 | } | 404 | } |
405 | 405 | ||
406 | static int fastboot_add(struct usb_configuration *c) | 406 | static int fastboot_add(struct usb_configuration *c) |
407 | { | 407 | { |
408 | struct f_fastboot *f_fb = fastboot_func; | 408 | struct f_fastboot *f_fb = fastboot_func; |
409 | int status; | 409 | int status; |
410 | 410 | ||
411 | debug("%s: cdev: 0x%p\n", __func__, c->cdev); | 411 | debug("%s: cdev: 0x%p\n", __func__, c->cdev); |
412 | 412 | ||
413 | if (!f_fb) { | 413 | if (!f_fb) { |
414 | f_fb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_fb)); | 414 | f_fb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_fb)); |
415 | if (!f_fb) | 415 | if (!f_fb) |
416 | return -ENOMEM; | 416 | return -ENOMEM; |
417 | 417 | ||
418 | fastboot_func = f_fb; | 418 | fastboot_func = f_fb; |
419 | memset(f_fb, 0, sizeof(*f_fb)); | 419 | memset(f_fb, 0, sizeof(*f_fb)); |
420 | } | 420 | } |
421 | 421 | ||
422 | f_fb->usb_function.name = "f_fastboot"; | 422 | f_fb->usb_function.name = "f_fastboot"; |
423 | f_fb->usb_function.bind = fastboot_bind; | 423 | f_fb->usb_function.bind = fastboot_bind; |
424 | f_fb->usb_function.unbind = fastboot_unbind; | 424 | f_fb->usb_function.unbind = fastboot_unbind; |
425 | f_fb->usb_function.set_alt = fastboot_set_alt; | 425 | f_fb->usb_function.set_alt = fastboot_set_alt; |
426 | f_fb->usb_function.disable = fastboot_disable; | 426 | f_fb->usb_function.disable = fastboot_disable; |
427 | f_fb->usb_function.strings = fastboot_strings; | 427 | f_fb->usb_function.strings = fastboot_strings; |
428 | 428 | ||
429 | status = usb_add_function(c, &f_fb->usb_function); | 429 | status = usb_add_function(c, &f_fb->usb_function); |
430 | if (status) { | 430 | if (status) { |
431 | free(f_fb); | 431 | free(f_fb); |
432 | fastboot_func = f_fb; | 432 | fastboot_func = f_fb; |
433 | } | 433 | } |
434 | 434 | ||
435 | return status; | 435 | return status; |
436 | } | 436 | } |
437 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add); | 437 | DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add); |
438 | 438 | ||
439 | int fastboot_tx_write_more(const char *buffer) | 439 | int fastboot_tx_write_more(const char *buffer) |
440 | { | 440 | { |
441 | int ret = 0; | 441 | int ret = 0; |
442 | 442 | ||
443 | /* alloc usb request FIFO node */ | 443 | /* alloc usb request FIFO node */ |
444 | usb_req *req = (usb_req *)malloc(sizeof(usb_req)); | 444 | usb_req *req = (usb_req *)malloc(sizeof(usb_req)); |
445 | if (!req) { | 445 | if (!req) { |
446 | printf("failed alloc usb req!\n"); | 446 | printf("failed alloc usb req!\n"); |
447 | return -ENOMEM; | 447 | return -ENOMEM; |
448 | } | 448 | } |
449 | 449 | ||
450 | /* usb request node FIFO enquene */ | 450 | /* usb request node FIFO enquene */ |
451 | if ((fastboot_func->front == NULL) && (fastboot_func->rear == NULL)) { | 451 | if ((fastboot_func->front == NULL) && (fastboot_func->rear == NULL)) { |
452 | fastboot_func->front = fastboot_func->rear = req; | 452 | fastboot_func->front = fastboot_func->rear = req; |
453 | req->next = NULL; | 453 | req->next = NULL; |
454 | } else { | 454 | } else { |
455 | fastboot_func->rear->next = req; | 455 | fastboot_func->rear->next = req; |
456 | fastboot_func->rear = req; | 456 | fastboot_func->rear = req; |
457 | req->next = NULL; | 457 | req->next = NULL; |
458 | } | 458 | } |
459 | 459 | ||
460 | /* alloc in request for current node */ | 460 | /* alloc in request for current node */ |
461 | req->in_req = fastboot_start_ep(fastboot_func->in_ep); | 461 | req->in_req = fastboot_start_ep(fastboot_func->in_ep); |
462 | if (!req->in_req) { | 462 | if (!req->in_req) { |
463 | printf("failed alloc req in\n"); | 463 | printf("failed alloc req in\n"); |
464 | fastboot_disable(&(fastboot_func->usb_function)); | 464 | fastboot_disable(&(fastboot_func->usb_function)); |
465 | return -EINVAL; | 465 | return -EINVAL; |
466 | } | 466 | } |
467 | req->in_req->complete = fastboot_fifo_complete; | 467 | req->in_req->complete = fastboot_fifo_complete; |
468 | 468 | ||
469 | memcpy(req->in_req->buf, buffer, strlen(buffer)); | 469 | memcpy(req->in_req->buf, buffer, strlen(buffer)); |
470 | req->in_req->length = strlen(buffer); | 470 | req->in_req->length = strlen(buffer); |
471 | 471 | ||
472 | ret = usb_ep_queue(fastboot_func->in_ep, req->in_req, 0); | 472 | ret = usb_ep_queue(fastboot_func->in_ep, req->in_req, 0); |
473 | if (ret) { | 473 | if (ret) { |
474 | printf("Error %d on queue\n", ret); | 474 | printf("Error %d on queue\n", ret); |
475 | return -EINVAL; | 475 | return -EINVAL; |
476 | } | 476 | } |
477 | 477 | ||
478 | ret = 0; | 478 | ret = 0; |
479 | return ret; | 479 | return ret; |
480 | } | 480 | } |
481 | 481 | ||
482 | int fastboot_tx_write(const char *buffer, unsigned int buffer_size) | 482 | int fastboot_tx_write(const char *buffer, unsigned int buffer_size) |
483 | { | 483 | { |
484 | struct usb_request *in_req = fastboot_func->in_req; | 484 | struct usb_request *in_req = fastboot_func->in_req; |
485 | int ret; | 485 | int ret; |
486 | 486 | ||
487 | if (!buffer_size) | 487 | if (!buffer_size) |
488 | return 0; | 488 | return 0; |
489 | 489 | ||
490 | memcpy(in_req->buf, buffer, buffer_size); | 490 | memcpy(in_req->buf, buffer, buffer_size); |
491 | in_req->length = buffer_size; | 491 | in_req->length = buffer_size; |
492 | 492 | ||
493 | usb_ep_dequeue(fastboot_func->in_ep, in_req); | 493 | usb_ep_dequeue(fastboot_func->in_ep, in_req); |
494 | 494 | ||
495 | ret = usb_ep_queue(fastboot_func->in_ep, in_req, 0); | 495 | ret = usb_ep_queue(fastboot_func->in_ep, in_req, 0); |
496 | if (ret) | 496 | if (ret) |
497 | printf("Error %d on queue\n", ret); | 497 | printf("Error %d on queue\n", ret); |
498 | return 0; | 498 | return 0; |
499 | } | 499 | } |
500 | 500 | ||
501 | static int fastboot_tx_write_str(const char *buffer) | 501 | static int fastboot_tx_write_str(const char *buffer) |
502 | { | 502 | { |
503 | return fastboot_tx_write(buffer, strlen(buffer)); | 503 | return fastboot_tx_write(buffer, strlen(buffer)); |
504 | } | 504 | } |
505 | 505 | ||
506 | static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) | 506 | static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) |
507 | { | 507 | { |
508 | do_reset(NULL, 0, 0, NULL); | 508 | do_reset(NULL, 0, 0, NULL); |
509 | } | 509 | } |
510 | 510 | ||
511 | static unsigned int rx_bytes_expected(struct usb_ep *ep) | 511 | static unsigned int rx_bytes_expected(struct usb_ep *ep) |
512 | { | 512 | { |
513 | int rx_remain = fastboot_data_remaining(); | 513 | int rx_remain = fastboot_data_remaining(); |
514 | unsigned int rem; | 514 | unsigned int rem; |
515 | unsigned int maxpacket = usb_endpoint_maxp(ep->desc); | 515 | unsigned int maxpacket = usb_endpoint_maxp(ep->desc); |
516 | 516 | ||
517 | if (rx_remain <= 0) | 517 | if (rx_remain <= 0) |
518 | return 0; | 518 | return 0; |
519 | else if (rx_remain > EP_BUFFER_SIZE) | 519 | else if (rx_remain > EP_BUFFER_SIZE) |
520 | return EP_BUFFER_SIZE; | 520 | return EP_BUFFER_SIZE; |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * Some controllers e.g. DWC3 don't like OUT transfers to be | 523 | * Some controllers e.g. DWC3 don't like OUT transfers to be |
524 | * not ending in maxpacket boundary. So just make them happy by | 524 | * not ending in maxpacket boundary. So just make them happy by |
525 | * always requesting for integral multiple of maxpackets. | 525 | * always requesting for integral multiple of maxpackets. |
526 | * This shouldn't bother controllers that don't care about it. | 526 | * This shouldn't bother controllers that don't care about it. |
527 | */ | 527 | */ |
528 | rem = rx_remain % maxpacket; | 528 | rem = rx_remain % maxpacket; |
529 | if (rem > 0) | 529 | if (rem > 0) |
530 | rx_remain = rx_remain + (maxpacket - rem); | 530 | rx_remain = rx_remain + (maxpacket - rem); |
531 | 531 | ||
532 | return rx_remain; | 532 | return rx_remain; |
533 | } | 533 | } |
534 | 534 | ||
535 | static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) | 535 | static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) |
536 | { | 536 | { |
537 | char response[FASTBOOT_RESPONSE_LEN] = {0}; | 537 | char response[FASTBOOT_RESPONSE_LEN] = {0}; |
538 | unsigned int transfer_size = fastboot_data_remaining(); | 538 | unsigned int transfer_size = fastboot_data_remaining(); |
539 | const unsigned char *buffer = req->buf; | 539 | const unsigned char *buffer = req->buf; |
540 | unsigned int buffer_size = req->actual; | 540 | unsigned int buffer_size = req->actual; |
541 | 541 | ||
542 | if (req->status != 0) { | 542 | if (req->status != 0) { |
543 | printf("Bad status: %d\n", req->status); | 543 | printf("Bad status: %d\n", req->status); |
544 | return; | 544 | return; |
545 | } | 545 | } |
546 | 546 | ||
547 | if (buffer_size < transfer_size) | 547 | if (buffer_size < transfer_size) |
548 | transfer_size = buffer_size; | 548 | transfer_size = buffer_size; |
549 | 549 | ||
550 | fastboot_data_download(buffer, transfer_size, response); | 550 | fastboot_data_download(buffer, transfer_size, response); |
551 | if (response[0]) { | 551 | if (response[0]) { |
552 | fastboot_tx_write_str(response); | 552 | fastboot_tx_write_str(response); |
553 | } else if (!fastboot_data_remaining()) { | 553 | } else if (!fastboot_data_remaining()) { |
554 | fastboot_data_complete(response); | 554 | fastboot_data_complete(response); |
555 | 555 | ||
556 | /* | 556 | /* |
557 | * Reset global transfer variable | 557 | * Reset global transfer variable |
558 | */ | 558 | */ |
559 | req->complete = rx_handler_command; | 559 | req->complete = rx_handler_command; |
560 | req->length = EP_BUFFER_SIZE; | 560 | req->length = EP_BUFFER_SIZE; |
561 | 561 | ||
562 | fastboot_tx_write_str(response); | 562 | fastboot_tx_write_str(response); |
563 | } else { | 563 | } else { |
564 | req->length = rx_bytes_expected(ep); | 564 | req->length = rx_bytes_expected(ep); |
565 | } | 565 | } |
566 | 566 | ||
567 | req->actual = 0; | 567 | req->actual = 0; |
568 | usb_ep_queue(ep, req, 0); | 568 | usb_ep_queue(ep, req, 0); |
569 | } | 569 | } |
570 | 570 | ||
571 | static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req) | 571 | static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req) |
572 | { | 572 | { |
573 | g_dnl_trigger_detach(); | 573 | g_dnl_trigger_detach(); |
574 | } | 574 | } |
575 | 575 | ||
576 | static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) | 576 | static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) |
577 | { | 577 | { |
578 | fastboot_boot(); | 578 | fastboot_boot(); |
579 | do_exit_on_complete(ep, req); | 579 | do_exit_on_complete(ep, req); |
580 | } | 580 | } |
581 | 581 | ||
582 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 582 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
583 | static void do_acmd_complete(struct usb_ep *ep, struct usb_request *req) | 583 | static void do_acmd_complete(struct usb_ep *ep, struct usb_request *req) |
584 | { | 584 | { |
585 | /* When usb dequeue complete will be called | 585 | /* When usb dequeue complete will be called |
586 | * Need status value before call run_command. | 586 | * Need status value before call run_command. |
587 | * otherwise, host can't get last message. | 587 | * otherwise, host can't get last message. |
588 | */ | 588 | */ |
589 | if(req->status == 0) | 589 | if(req->status == 0) |
590 | fastboot_acmd_complete(); | 590 | fastboot_acmd_complete(); |
591 | } | 591 | } |
592 | #endif | 592 | #endif |
593 | 593 | ||
594 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) | 594 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) |
595 | { | 595 | { |
596 | char *cmdbuf = req->buf; | 596 | char *cmdbuf = req->buf; |
597 | char response[FASTBOOT_RESPONSE_LEN] = {0}; | 597 | char response[FASTBOOT_RESPONSE_LEN] = {0}; |
598 | int cmd = -1; | 598 | int cmd = -1; |
599 | 599 | ||
600 | /* init in request FIFO pointer */ | 600 | /* init in request FIFO pointer */ |
601 | fastboot_func->front = NULL; | 601 | fastboot_func->front = NULL; |
602 | fastboot_func->rear = NULL; | 602 | fastboot_func->rear = NULL; |
603 | 603 | ||
604 | if (req->status != 0 || req->length == 0) | 604 | if (req->status != 0 || req->length == 0) |
605 | return; | 605 | return; |
606 | 606 | ||
607 | if (req->actual < req->length) { | 607 | if (req->actual < req->length) { |
608 | cmdbuf[req->actual] = '\0'; | 608 | cmdbuf[req->actual] = '\0'; |
609 | cmd = fastboot_handle_command(cmdbuf, response); | 609 | cmd = fastboot_handle_command(cmdbuf, response); |
610 | } else { | 610 | } else { |
611 | pr_err("buffer overflow"); | 611 | pr_err("buffer overflow"); |
612 | fastboot_fail("buffer overflow", response); | 612 | fastboot_fail("buffer overflow", response); |
613 | } | 613 | } |
614 | 614 | ||
615 | if (!strncmp("DATA", response, 4)) { | 615 | if (!strncmp("DATA", response, 4)) { |
616 | req->complete = rx_handler_dl_image; | 616 | req->complete = rx_handler_dl_image; |
617 | req->length = rx_bytes_expected(ep); | 617 | req->length = rx_bytes_expected(ep); |
618 | } | 618 | } |
619 | 619 | ||
620 | fastboot_tx_write_str(response); | 620 | fastboot_tx_write_str(response); |
621 | 621 | ||
622 | if (!strncmp("OKAY", response, 4)) { | 622 | if (!strncmp("OKAY", response, 4)) { |
623 | switch (cmd) { | 623 | switch (cmd) { |
624 | case FASTBOOT_COMMAND_BOOT: | 624 | case FASTBOOT_COMMAND_BOOT: |
625 | fastboot_func->in_req->complete = do_bootm_on_complete; | 625 | fastboot_func->in_req->complete = do_bootm_on_complete; |
626 | break; | 626 | break; |
627 | 627 | ||
628 | case FASTBOOT_COMMAND_CONTINUE: | 628 | case FASTBOOT_COMMAND_CONTINUE: |
629 | fastboot_func->in_req->complete = do_exit_on_complete; | 629 | fastboot_func->in_req->complete = do_exit_on_complete; |
630 | break; | 630 | break; |
631 | 631 | ||
632 | case FASTBOOT_COMMAND_REBOOT: | 632 | case FASTBOOT_COMMAND_REBOOT: |
633 | case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: | 633 | case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: |
634 | #ifdef CONFIG_ANDROID_RECOVERY | ||
635 | case FASTBOOT_COMMAND_RECOVERY_FASTBOOT: | ||
636 | #endif | ||
634 | fastboot_func->in_req->complete = compl_do_reset; | 637 | fastboot_func->in_req->complete = compl_do_reset; |
635 | break; | 638 | break; |
636 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 639 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
637 | case FASTBOOT_COMMAND_ACMD: | 640 | case FASTBOOT_COMMAND_ACMD: |
638 | fastboot_func->in_req->complete = do_acmd_complete; | 641 | fastboot_func->in_req->complete = do_acmd_complete; |
639 | break; | 642 | break; |
640 | #endif | 643 | #endif |
641 | } | 644 | } |
642 | } | 645 | } |
643 | 646 | ||
644 | *cmdbuf = '\0'; | 647 | *cmdbuf = '\0'; |
645 | req->actual = 0; | 648 | req->actual = 0; |
646 | usb_ep_queue(ep, req, 0); | 649 | usb_ep_queue(ep, req, 0); |
647 | } | 650 | } |
648 | 651 |
include/fastboot.h
1 | /* SPDX-License-Identifier: GPL-2.0+ */ | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* | 2 | /* |
3 | * (C) Copyright 2008 - 2009 | 3 | * (C) Copyright 2008 - 2009 |
4 | * Windriver, <www.windriver.com> | 4 | * Windriver, <www.windriver.com> |
5 | * Tom Rix <Tom.Rix@windriver.com> | 5 | * Tom Rix <Tom.Rix@windriver.com> |
6 | * | 6 | * |
7 | * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 7 | * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
8 | * | 8 | * |
9 | * Copyright 2014 Linaro, Ltd. | 9 | * Copyright 2014 Linaro, Ltd. |
10 | * Rob Herring <robh@kernel.org> | 10 | * Rob Herring <robh@kernel.org> |
11 | */ | 11 | */ |
12 | #ifndef _FASTBOOT_H_ | 12 | #ifndef _FASTBOOT_H_ |
13 | #define _FASTBOOT_H_ | 13 | #define _FASTBOOT_H_ |
14 | 14 | ||
15 | #define FASTBOOT_VERSION "0.4" | 15 | #define FASTBOOT_VERSION "0.4" |
16 | 16 | ||
17 | /* The 64 defined bytes plus \0 */ | 17 | /* The 64 defined bytes plus \0 */ |
18 | #define FASTBOOT_COMMAND_LEN (64 + 1) | 18 | #define FASTBOOT_COMMAND_LEN (64 + 1) |
19 | #define FASTBOOT_RESPONSE_LEN (64 + 1) | 19 | #define FASTBOOT_RESPONSE_LEN (64 + 1) |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * All known commands to fastboot | 22 | * All known commands to fastboot |
23 | */ | 23 | */ |
24 | enum { | 24 | enum { |
25 | FASTBOOT_COMMAND_GETVAR = 0, | 25 | FASTBOOT_COMMAND_GETVAR = 0, |
26 | FASTBOOT_COMMAND_DOWNLOAD, | 26 | FASTBOOT_COMMAND_DOWNLOAD, |
27 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) | 27 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
28 | FASTBOOT_COMMAND_FLASH, | 28 | FASTBOOT_COMMAND_FLASH, |
29 | FASTBOOT_COMMAND_ERASE, | 29 | FASTBOOT_COMMAND_ERASE, |
30 | #endif | 30 | #endif |
31 | FASTBOOT_COMMAND_BOOT, | 31 | FASTBOOT_COMMAND_BOOT, |
32 | FASTBOOT_COMMAND_CONTINUE, | 32 | FASTBOOT_COMMAND_CONTINUE, |
33 | FASTBOOT_COMMAND_REBOOT, | 33 | FASTBOOT_COMMAND_REBOOT, |
34 | FASTBOOT_COMMAND_REBOOT_BOOTLOADER, | 34 | FASTBOOT_COMMAND_REBOOT_BOOTLOADER, |
35 | FASTBOOT_COMMAND_SET_ACTIVE, | 35 | FASTBOOT_COMMAND_SET_ACTIVE, |
36 | #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT) | 36 | #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT) |
37 | FASTBOOT_COMMAND_OEM_FORMAT, | 37 | FASTBOOT_COMMAND_OEM_FORMAT, |
38 | #endif | 38 | #endif |
39 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 39 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
40 | FASTBOOT_COMMAND_ACMD, | 40 | FASTBOOT_COMMAND_ACMD, |
41 | FASTBOOT_COMMAND_UCMD, | 41 | FASTBOOT_COMMAND_UCMD, |
42 | #endif | 42 | #endif |
43 | #ifdef CONFIG_FSL_FASTBOOT | 43 | #ifdef CONFIG_FSL_FASTBOOT |
44 | FASTBOOT_COMMAND_UPLOAD, | 44 | FASTBOOT_COMMAND_UPLOAD, |
45 | FASTBOOT_COMMAND_GETSTAGED, | 45 | FASTBOOT_COMMAND_GETSTAGED, |
46 | #ifdef CONFIG_FASTBOOT_LOCK | 46 | #ifdef CONFIG_FASTBOOT_LOCK |
47 | FASTBOOT_COMMAND_FLASHING, | 47 | FASTBOOT_COMMAND_FLASHING, |
48 | FASTBOOT_COMMAND_OEM, | 48 | FASTBOOT_COMMAND_OEM, |
49 | #endif | 49 | #endif |
50 | #ifdef CONFIG_AVB_SUPPORT | 50 | #ifdef CONFIG_AVB_SUPPORT |
51 | FASTBOOT_COMMAND_SETACTIVE, | 51 | FASTBOOT_COMMAND_SETACTIVE, |
52 | #endif | 52 | #endif |
53 | #ifdef CONFIG_AVB_ATX | 53 | #ifdef CONFIG_AVB_ATX |
54 | FASTBOOT_COMMAND_STAGE, | 54 | FASTBOOT_COMMAND_STAGE, |
55 | #endif | 55 | #endif |
56 | #endif | 56 | #endif |
57 | #ifdef CONFIG_ANDROID_RECOVERY | ||
58 | FASTBOOT_COMMAND_RECOVERY_FASTBOOT, | ||
59 | #endif | ||
57 | FASTBOOT_COMMAND_COUNT | 60 | FASTBOOT_COMMAND_COUNT |
58 | }; | 61 | }; |
59 | 62 | ||
60 | /** | 63 | /** |
61 | * fastboot_response() - Writes a response of the form "$tag$reason". | 64 | * fastboot_response() - Writes a response of the form "$tag$reason". |
62 | * | 65 | * |
63 | * @tag: The first part of the response | 66 | * @tag: The first part of the response |
64 | * @response: Pointer to fastboot response buffer | 67 | * @response: Pointer to fastboot response buffer |
65 | * @format: printf style format string | 68 | * @format: printf style format string |
66 | */ | 69 | */ |
67 | void fastboot_response(const char *tag, char *response, | 70 | void fastboot_response(const char *tag, char *response, |
68 | const char *format, ...) | 71 | const char *format, ...) |
69 | __attribute__ ((format (__printf__, 3, 4))); | 72 | __attribute__ ((format (__printf__, 3, 4))); |
70 | 73 | ||
71 | /** | 74 | /** |
72 | * fastboot_fail() - Write a FAIL response of the form "FAIL$reason". | 75 | * fastboot_fail() - Write a FAIL response of the form "FAIL$reason". |
73 | * | 76 | * |
74 | * @reason: Pointer to returned reason string | 77 | * @reason: Pointer to returned reason string |
75 | * @response: Pointer to fastboot response buffer | 78 | * @response: Pointer to fastboot response buffer |
76 | */ | 79 | */ |
77 | void fastboot_fail(const char *reason, char *response); | 80 | void fastboot_fail(const char *reason, char *response); |
78 | 81 | ||
79 | /** | 82 | /** |
80 | * fastboot_okay() - Write an OKAY response of the form "OKAY$reason". | 83 | * fastboot_okay() - Write an OKAY response of the form "OKAY$reason". |
81 | * | 84 | * |
82 | * @reason: Pointer to returned reason string, or NULL to send a bare "OKAY" | 85 | * @reason: Pointer to returned reason string, or NULL to send a bare "OKAY" |
83 | * @response: Pointer to fastboot response buffer | 86 | * @response: Pointer to fastboot response buffer |
84 | */ | 87 | */ |
85 | void fastboot_okay(const char *reason, char *response); | 88 | void fastboot_okay(const char *reason, char *response); |
86 | 89 | ||
87 | /** | 90 | /** |
88 | * fastboot_set_reboot_flag() - Set flag to indicate reboot-bootloader | 91 | * fastboot_set_reboot_flag() - Set flag to indicate reboot-bootloader |
89 | * | 92 | * |
90 | * Set flag which indicates that we should reboot into the bootloader | 93 | * Set flag which indicates that we should reboot into the bootloader |
91 | * following the reboot that fastboot executes after this function. | 94 | * following the reboot that fastboot executes after this function. |
92 | * | 95 | * |
93 | * This function should be overridden in your board file with one | 96 | * This function should be overridden in your board file with one |
94 | * which sets whatever flag your board specific Android bootloader flow | 97 | * which sets whatever flag your board specific Android bootloader flow |
95 | * requires in order to re-enter the bootloader. | 98 | * requires in order to re-enter the bootloader. |
96 | */ | 99 | */ |
97 | int fastboot_set_reboot_flag(void); | 100 | int fastboot_set_reboot_flag(void); |
98 | 101 | ||
99 | /** | 102 | /** |
100 | * fastboot_set_progress_callback() - set progress callback | 103 | * fastboot_set_progress_callback() - set progress callback |
101 | * | 104 | * |
102 | * @progress: Pointer to progress callback | 105 | * @progress: Pointer to progress callback |
103 | * | 106 | * |
104 | * Set a callback which is invoked periodically during long running operations | 107 | * Set a callback which is invoked periodically during long running operations |
105 | * (flash and erase). This can be used (for example) by the UDP transport to | 108 | * (flash and erase). This can be used (for example) by the UDP transport to |
106 | * send INFO responses to keep the client alive whilst those commands are | 109 | * send INFO responses to keep the client alive whilst those commands are |
107 | * executing. | 110 | * executing. |
108 | */ | 111 | */ |
109 | void fastboot_set_progress_callback(void (*progress)(const char *msg)); | 112 | void fastboot_set_progress_callback(void (*progress)(const char *msg)); |
110 | 113 | ||
111 | /* | 114 | /* |
112 | * fastboot_init() - initialise new fastboot protocol session | 115 | * fastboot_init() - initialise new fastboot protocol session |
113 | * | 116 | * |
114 | * @buf_addr: Pointer to download buffer, or NULL for default | 117 | * @buf_addr: Pointer to download buffer, or NULL for default |
115 | * @buf_size: Size of download buffer, or zero for default | 118 | * @buf_size: Size of download buffer, or zero for default |
116 | */ | 119 | */ |
117 | void fastboot_init(void *buf_addr, u32 buf_size); | 120 | void fastboot_init(void *buf_addr, u32 buf_size); |
118 | 121 | ||
119 | /** | 122 | /** |
120 | * fastboot_boot() - Execute fastboot boot command | 123 | * fastboot_boot() - Execute fastboot boot command |
121 | * | 124 | * |
122 | * If ${fastboot_bootcmd} is set, run that command to execute the boot | 125 | * If ${fastboot_bootcmd} is set, run that command to execute the boot |
123 | * process, if that returns, then exit the fastboot server and return | 126 | * process, if that returns, then exit the fastboot server and return |
124 | * control to the caller. | 127 | * control to the caller. |
125 | * | 128 | * |
126 | * Otherwise execute "bootm <fastboot_buf_addr>", if that fails, reset | 129 | * Otherwise execute "bootm <fastboot_buf_addr>", if that fails, reset |
127 | * the board. | 130 | * the board. |
128 | */ | 131 | */ |
129 | void fastboot_boot(void); | 132 | void fastboot_boot(void); |
130 | 133 | ||
131 | /** | 134 | /** |
132 | * fastboot_handle_command() - Handle fastboot command | 135 | * fastboot_handle_command() - Handle fastboot command |
133 | * | 136 | * |
134 | * @cmd_string: Pointer to command string | 137 | * @cmd_string: Pointer to command string |
135 | * @response: Pointer to fastboot response buffer | 138 | * @response: Pointer to fastboot response buffer |
136 | * | 139 | * |
137 | * Return: Executed command, or -1 if not recognized | 140 | * Return: Executed command, or -1 if not recognized |
138 | */ | 141 | */ |
139 | int fastboot_handle_command(char *cmd_string, char *response); | 142 | int fastboot_handle_command(char *cmd_string, char *response); |
140 | 143 | ||
141 | /** | 144 | /** |
142 | * fastboot_data_remaining() - return bytes remaining in current transfer | 145 | * fastboot_data_remaining() - return bytes remaining in current transfer |
143 | * | 146 | * |
144 | * Return: Number of bytes left in the current download | 147 | * Return: Number of bytes left in the current download |
145 | */ | 148 | */ |
146 | u32 fastboot_data_remaining(void); | 149 | u32 fastboot_data_remaining(void); |
147 | 150 | ||
148 | /** | 151 | /** |
149 | * fastboot_data_download() - Copy image data to fastboot_buf_addr. | 152 | * fastboot_data_download() - Copy image data to fastboot_buf_addr. |
150 | * | 153 | * |
151 | * @fastboot_data: Pointer to received fastboot data | 154 | * @fastboot_data: Pointer to received fastboot data |
152 | * @fastboot_data_len: Length of received fastboot data | 155 | * @fastboot_data_len: Length of received fastboot data |
153 | * @response: Pointer to fastboot response buffer | 156 | * @response: Pointer to fastboot response buffer |
154 | * | 157 | * |
155 | * Copies image data from fastboot_data to fastboot_buf_addr. Writes to | 158 | * Copies image data from fastboot_data to fastboot_buf_addr. Writes to |
156 | * response. fastboot_bytes_received is updated to indicate the number | 159 | * response. fastboot_bytes_received is updated to indicate the number |
157 | * of bytes that have been transferred. | 160 | * of bytes that have been transferred. |
158 | */ | 161 | */ |
159 | void fastboot_data_download(const void *fastboot_data, | 162 | void fastboot_data_download(const void *fastboot_data, |
160 | unsigned int fastboot_data_len, char *response); | 163 | unsigned int fastboot_data_len, char *response); |
161 | 164 | ||
162 | /** | 165 | /** |
163 | * fastboot_data_complete() - Mark current transfer complete | 166 | * fastboot_data_complete() - Mark current transfer complete |
164 | * | 167 | * |
165 | * @response: Pointer to fastboot response buffer | 168 | * @response: Pointer to fastboot response buffer |
166 | * | 169 | * |
167 | * Set image_size and ${filesize} to the total size of the downloaded image. | 170 | * Set image_size and ${filesize} to the total size of the downloaded image. |
168 | */ | 171 | */ |
169 | void fastboot_data_complete(char *response); | 172 | void fastboot_data_complete(char *response); |
170 | 173 | ||
171 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) | 174 | #if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) |
172 | void fastboot_acmd_complete(void); | 175 | void fastboot_acmd_complete(void); |
173 | #endif | 176 | #endif |
174 | 177 | ||
175 | int fastboot_tx_write_more(const char *buffer); | 178 | int fastboot_tx_write_more(const char *buffer); |
176 | 179 | ||
177 | int fastboot_tx_write(const char *buffer, unsigned int buffer_size); | 180 | int fastboot_tx_write(const char *buffer, unsigned int buffer_size); |
178 | 181 | ||
179 | #endif /* _FASTBOOT_H_ */ | 182 | #endif /* _FASTBOOT_H_ */ |
180 | 183 |
net/fastboot.c
1 | // SPDX-License-Identifier: BSD-2-Clause | 1 | // SPDX-License-Identifier: BSD-2-Clause |
2 | /* | 2 | /* |
3 | * Copyright (C) 2016 The Android Open Source Project | 3 | * Copyright (C) 2016 The Android Open Source Project |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <common.h> | 6 | #include <common.h> |
7 | #include <fastboot.h> | 7 | #include <fastboot.h> |
8 | #include <net.h> | 8 | #include <net.h> |
9 | #include <net/fastboot.h> | 9 | #include <net/fastboot.h> |
10 | 10 | ||
11 | /* Fastboot port # defined in spec */ | 11 | /* Fastboot port # defined in spec */ |
12 | #define WELL_KNOWN_PORT 5554 | 12 | #define WELL_KNOWN_PORT 5554 |
13 | 13 | ||
14 | enum { | 14 | enum { |
15 | FASTBOOT_ERROR = 0, | 15 | FASTBOOT_ERROR = 0, |
16 | FASTBOOT_QUERY = 1, | 16 | FASTBOOT_QUERY = 1, |
17 | FASTBOOT_INIT = 2, | 17 | FASTBOOT_INIT = 2, |
18 | FASTBOOT_FASTBOOT = 3, | 18 | FASTBOOT_FASTBOOT = 3, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | struct __packed fastboot_header { | 21 | struct __packed fastboot_header { |
22 | uchar id; | 22 | uchar id; |
23 | uchar flags; | 23 | uchar flags; |
24 | unsigned short seq; | 24 | unsigned short seq; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | #define PACKET_SIZE 1024 | 27 | #define PACKET_SIZE 1024 |
28 | #define DATA_SIZE (PACKET_SIZE - sizeof(struct fastboot_header)) | 28 | #define DATA_SIZE (PACKET_SIZE - sizeof(struct fastboot_header)) |
29 | 29 | ||
30 | /* Sequence number sent for every packet */ | 30 | /* Sequence number sent for every packet */ |
31 | static unsigned short sequence_number = 1; | 31 | static unsigned short sequence_number = 1; |
32 | static const unsigned short packet_size = PACKET_SIZE; | 32 | static const unsigned short packet_size = PACKET_SIZE; |
33 | static const unsigned short udp_version = 1; | 33 | static const unsigned short udp_version = 1; |
34 | 34 | ||
35 | /* Keep track of last packet for resubmission */ | 35 | /* Keep track of last packet for resubmission */ |
36 | static uchar last_packet[PACKET_SIZE]; | 36 | static uchar last_packet[PACKET_SIZE]; |
37 | static unsigned int last_packet_len; | 37 | static unsigned int last_packet_len; |
38 | 38 | ||
39 | static struct in_addr fastboot_remote_ip; | 39 | static struct in_addr fastboot_remote_ip; |
40 | /* The UDP port at their end */ | 40 | /* The UDP port at their end */ |
41 | static int fastboot_remote_port; | 41 | static int fastboot_remote_port; |
42 | /* The UDP port at our end */ | 42 | /* The UDP port at our end */ |
43 | static int fastboot_our_port; | 43 | static int fastboot_our_port; |
44 | 44 | ||
45 | static void boot_downloaded_image(void); | 45 | static void boot_downloaded_image(void); |
46 | 46 | ||
47 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) | 47 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
48 | /** | 48 | /** |
49 | * fastboot_udp_send_info() - Send an INFO packet during long commands. | 49 | * fastboot_udp_send_info() - Send an INFO packet during long commands. |
50 | * | 50 | * |
51 | * @msg: String describing the reason for waiting | 51 | * @msg: String describing the reason for waiting |
52 | */ | 52 | */ |
53 | static void fastboot_udp_send_info(const char *msg) | 53 | static void fastboot_udp_send_info(const char *msg) |
54 | { | 54 | { |
55 | uchar *packet; | 55 | uchar *packet; |
56 | uchar *packet_base; | 56 | uchar *packet_base; |
57 | int len = 0; | 57 | int len = 0; |
58 | char response[FASTBOOT_RESPONSE_LEN] = {0}; | 58 | char response[FASTBOOT_RESPONSE_LEN] = {0}; |
59 | 59 | ||
60 | struct fastboot_header response_header = { | 60 | struct fastboot_header response_header = { |
61 | .id = FASTBOOT_FASTBOOT, | 61 | .id = FASTBOOT_FASTBOOT, |
62 | .flags = 0, | 62 | .flags = 0, |
63 | .seq = htons(sequence_number) | 63 | .seq = htons(sequence_number) |
64 | }; | 64 | }; |
65 | ++sequence_number; | 65 | ++sequence_number; |
66 | packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; | 66 | packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; |
67 | packet_base = packet; | 67 | packet_base = packet; |
68 | 68 | ||
69 | /* Write headers */ | 69 | /* Write headers */ |
70 | memcpy(packet, &response_header, sizeof(response_header)); | 70 | memcpy(packet, &response_header, sizeof(response_header)); |
71 | packet += sizeof(response_header); | 71 | packet += sizeof(response_header); |
72 | /* Write response */ | 72 | /* Write response */ |
73 | fastboot_response("INFO", response, "%s", msg); | 73 | fastboot_response("INFO", response, "%s", msg); |
74 | memcpy(packet, response, strlen(response)); | 74 | memcpy(packet, response, strlen(response)); |
75 | packet += strlen(response); | 75 | packet += strlen(response); |
76 | 76 | ||
77 | len = packet - packet_base; | 77 | len = packet - packet_base; |
78 | 78 | ||
79 | /* Save packet for retransmitting */ | 79 | /* Save packet for retransmitting */ |
80 | last_packet_len = len; | 80 | last_packet_len = len; |
81 | memcpy(last_packet, packet_base, last_packet_len); | 81 | memcpy(last_packet, packet_base, last_packet_len); |
82 | 82 | ||
83 | net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, | 83 | net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, |
84 | fastboot_remote_port, fastboot_our_port, len); | 84 | fastboot_remote_port, fastboot_our_port, len); |
85 | } | 85 | } |
86 | 86 | ||
87 | /** | 87 | /** |
88 | * fastboot_timed_send_info() - Send INFO packet every 30 seconds | 88 | * fastboot_timed_send_info() - Send INFO packet every 30 seconds |
89 | * | 89 | * |
90 | * @msg: String describing the reason for waiting | 90 | * @msg: String describing the reason for waiting |
91 | * | 91 | * |
92 | * Send an INFO packet during long commands based on timer. An INFO packet | 92 | * Send an INFO packet during long commands based on timer. An INFO packet |
93 | * is sent if the time is 30 seconds after start. Else, noop. | 93 | * is sent if the time is 30 seconds after start. Else, noop. |
94 | */ | 94 | */ |
95 | static void fastboot_timed_send_info(const char *msg) | 95 | static void fastboot_timed_send_info(const char *msg) |
96 | { | 96 | { |
97 | static ulong start; | 97 | static ulong start; |
98 | 98 | ||
99 | /* Initialize timer */ | 99 | /* Initialize timer */ |
100 | if (start == 0) | 100 | if (start == 0) |
101 | start = get_timer(0); | 101 | start = get_timer(0); |
102 | ulong time = get_timer(start); | 102 | ulong time = get_timer(start); |
103 | /* Send INFO packet to host every 30 seconds */ | 103 | /* Send INFO packet to host every 30 seconds */ |
104 | if (time >= 30000) { | 104 | if (time >= 30000) { |
105 | start = get_timer(0); | 105 | start = get_timer(0); |
106 | fastboot_udp_send_info(msg); | 106 | fastboot_udp_send_info(msg); |
107 | } | 107 | } |
108 | } | 108 | } |
109 | #endif | 109 | #endif |
110 | 110 | ||
111 | /** | 111 | /** |
112 | * fastboot_send() - Sends a packet in response to received fastboot packet | 112 | * fastboot_send() - Sends a packet in response to received fastboot packet |
113 | * | 113 | * |
114 | * @header: Header for response packet | 114 | * @header: Header for response packet |
115 | * @fastboot_data: Pointer to received fastboot data | 115 | * @fastboot_data: Pointer to received fastboot data |
116 | * @fastboot_data_len: Length of received fastboot data | 116 | * @fastboot_data_len: Length of received fastboot data |
117 | * @retransmit: Nonzero if sending last sent packet | 117 | * @retransmit: Nonzero if sending last sent packet |
118 | */ | 118 | */ |
119 | static void fastboot_send(struct fastboot_header header, char *fastboot_data, | 119 | static void fastboot_send(struct fastboot_header header, char *fastboot_data, |
120 | unsigned int fastboot_data_len, uchar retransmit) | 120 | unsigned int fastboot_data_len, uchar retransmit) |
121 | { | 121 | { |
122 | uchar *packet; | 122 | uchar *packet; |
123 | uchar *packet_base; | 123 | uchar *packet_base; |
124 | int len = 0; | 124 | int len = 0; |
125 | const char *error_msg = "An error occurred."; | 125 | const char *error_msg = "An error occurred."; |
126 | short tmp; | 126 | short tmp; |
127 | struct fastboot_header response_header = header; | 127 | struct fastboot_header response_header = header; |
128 | static char command[FASTBOOT_COMMAND_LEN]; | 128 | static char command[FASTBOOT_COMMAND_LEN]; |
129 | static int cmd = -1; | 129 | static int cmd = -1; |
130 | static bool pending_command; | 130 | static bool pending_command; |
131 | char response[FASTBOOT_RESPONSE_LEN] = {0}; | 131 | char response[FASTBOOT_RESPONSE_LEN] = {0}; |
132 | 132 | ||
133 | /* | 133 | /* |
134 | * We will always be sending some sort of packet, so | 134 | * We will always be sending some sort of packet, so |
135 | * cobble together the packet headers now. | 135 | * cobble together the packet headers now. |
136 | */ | 136 | */ |
137 | packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; | 137 | packet = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; |
138 | packet_base = packet; | 138 | packet_base = packet; |
139 | 139 | ||
140 | /* Resend last packet */ | 140 | /* Resend last packet */ |
141 | if (retransmit) { | 141 | if (retransmit) { |
142 | memcpy(packet, last_packet, last_packet_len); | 142 | memcpy(packet, last_packet, last_packet_len); |
143 | net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, | 143 | net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, |
144 | fastboot_remote_port, fastboot_our_port, | 144 | fastboot_remote_port, fastboot_our_port, |
145 | last_packet_len); | 145 | last_packet_len); |
146 | return; | 146 | return; |
147 | } | 147 | } |
148 | 148 | ||
149 | response_header.seq = htons(response_header.seq); | 149 | response_header.seq = htons(response_header.seq); |
150 | memcpy(packet, &response_header, sizeof(response_header)); | 150 | memcpy(packet, &response_header, sizeof(response_header)); |
151 | packet += sizeof(response_header); | 151 | packet += sizeof(response_header); |
152 | 152 | ||
153 | switch (header.id) { | 153 | switch (header.id) { |
154 | case FASTBOOT_QUERY: | 154 | case FASTBOOT_QUERY: |
155 | tmp = htons(sequence_number); | 155 | tmp = htons(sequence_number); |
156 | memcpy(packet, &tmp, sizeof(tmp)); | 156 | memcpy(packet, &tmp, sizeof(tmp)); |
157 | packet += sizeof(tmp); | 157 | packet += sizeof(tmp); |
158 | break; | 158 | break; |
159 | case FASTBOOT_INIT: | 159 | case FASTBOOT_INIT: |
160 | tmp = htons(udp_version); | 160 | tmp = htons(udp_version); |
161 | memcpy(packet, &tmp, sizeof(tmp)); | 161 | memcpy(packet, &tmp, sizeof(tmp)); |
162 | packet += sizeof(tmp); | 162 | packet += sizeof(tmp); |
163 | tmp = htons(packet_size); | 163 | tmp = htons(packet_size); |
164 | memcpy(packet, &tmp, sizeof(tmp)); | 164 | memcpy(packet, &tmp, sizeof(tmp)); |
165 | packet += sizeof(tmp); | 165 | packet += sizeof(tmp); |
166 | break; | 166 | break; |
167 | case FASTBOOT_ERROR: | 167 | case FASTBOOT_ERROR: |
168 | memcpy(packet, error_msg, strlen(error_msg)); | 168 | memcpy(packet, error_msg, strlen(error_msg)); |
169 | packet += strlen(error_msg); | 169 | packet += strlen(error_msg); |
170 | break; | 170 | break; |
171 | case FASTBOOT_FASTBOOT: | 171 | case FASTBOOT_FASTBOOT: |
172 | if (cmd == FASTBOOT_COMMAND_DOWNLOAD) { | 172 | if (cmd == FASTBOOT_COMMAND_DOWNLOAD) { |
173 | if (!fastboot_data_len && !fastboot_data_remaining()) { | 173 | if (!fastboot_data_len && !fastboot_data_remaining()) { |
174 | fastboot_data_complete(response); | 174 | fastboot_data_complete(response); |
175 | } else { | 175 | } else { |
176 | fastboot_data_download(fastboot_data, | 176 | fastboot_data_download(fastboot_data, |
177 | fastboot_data_len, | 177 | fastboot_data_len, |
178 | response); | 178 | response); |
179 | } | 179 | } |
180 | } else if (!pending_command) { | 180 | } else if (!pending_command) { |
181 | strlcpy(command, fastboot_data, | 181 | strlcpy(command, fastboot_data, |
182 | min((size_t)fastboot_data_len + 1, | 182 | min((size_t)fastboot_data_len + 1, |
183 | sizeof(command))); | 183 | sizeof(command))); |
184 | pending_command = true; | 184 | pending_command = true; |
185 | } else { | 185 | } else { |
186 | cmd = fastboot_handle_command(command, response); | 186 | cmd = fastboot_handle_command(command, response); |
187 | pending_command = false; | 187 | pending_command = false; |
188 | } | 188 | } |
189 | /* | 189 | /* |
190 | * Sent some INFO packets, need to update sequence number in | 190 | * Sent some INFO packets, need to update sequence number in |
191 | * header | 191 | * header |
192 | */ | 192 | */ |
193 | if (header.seq != sequence_number) { | 193 | if (header.seq != sequence_number) { |
194 | response_header.seq = htons(sequence_number); | 194 | response_header.seq = htons(sequence_number); |
195 | memcpy(packet_base, &response_header, | 195 | memcpy(packet_base, &response_header, |
196 | sizeof(response_header)); | 196 | sizeof(response_header)); |
197 | } | 197 | } |
198 | /* Write response to packet */ | 198 | /* Write response to packet */ |
199 | memcpy(packet, response, strlen(response)); | 199 | memcpy(packet, response, strlen(response)); |
200 | packet += strlen(response); | 200 | packet += strlen(response); |
201 | break; | 201 | break; |
202 | default: | 202 | default: |
203 | pr_err("ID %d not implemented.\n", header.id); | 203 | pr_err("ID %d not implemented.\n", header.id); |
204 | return; | 204 | return; |
205 | } | 205 | } |
206 | 206 | ||
207 | len = packet - packet_base; | 207 | len = packet - packet_base; |
208 | 208 | ||
209 | /* Save packet for retransmitting */ | 209 | /* Save packet for retransmitting */ |
210 | last_packet_len = len; | 210 | last_packet_len = len; |
211 | memcpy(last_packet, packet_base, last_packet_len); | 211 | memcpy(last_packet, packet_base, last_packet_len); |
212 | 212 | ||
213 | net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, | 213 | net_send_udp_packet(net_server_ethaddr, fastboot_remote_ip, |
214 | fastboot_remote_port, fastboot_our_port, len); | 214 | fastboot_remote_port, fastboot_our_port, len); |
215 | 215 | ||
216 | /* Continue boot process after sending response */ | 216 | /* Continue boot process after sending response */ |
217 | if (!strncmp("OKAY", response, 4)) { | 217 | if (!strncmp("OKAY", response, 4)) { |
218 | switch (cmd) { | 218 | switch (cmd) { |
219 | case FASTBOOT_COMMAND_BOOT: | 219 | case FASTBOOT_COMMAND_BOOT: |
220 | boot_downloaded_image(); | 220 | boot_downloaded_image(); |
221 | break; | 221 | break; |
222 | 222 | ||
223 | case FASTBOOT_COMMAND_CONTINUE: | 223 | case FASTBOOT_COMMAND_CONTINUE: |
224 | net_set_state(NETLOOP_SUCCESS); | 224 | net_set_state(NETLOOP_SUCCESS); |
225 | break; | 225 | break; |
226 | 226 | ||
227 | case FASTBOOT_COMMAND_REBOOT: | 227 | case FASTBOOT_COMMAND_REBOOT: |
228 | case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: | 228 | case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: |
229 | #ifdef CONFIG_ANDROID_RECOVERY | ||
230 | case FASTBOOT_COMMAND_RECOVERY_FASTBOOT: | ||
231 | #endif | ||
229 | do_reset(NULL, 0, 0, NULL); | 232 | do_reset(NULL, 0, 0, NULL); |
230 | break; | 233 | break; |
231 | } | 234 | } |
232 | } | 235 | } |
233 | 236 | ||
234 | if (!strncmp("OKAY", response, 4) || !strncmp("FAIL", response, 4)) | 237 | if (!strncmp("OKAY", response, 4) || !strncmp("FAIL", response, 4)) |
235 | cmd = -1; | 238 | cmd = -1; |
236 | } | 239 | } |
237 | 240 | ||
238 | /** | 241 | /** |
239 | * boot_downloaded_image() - Boots into downloaded image. | 242 | * boot_downloaded_image() - Boots into downloaded image. |
240 | */ | 243 | */ |
241 | static void boot_downloaded_image(void) | 244 | static void boot_downloaded_image(void) |
242 | { | 245 | { |
243 | fastboot_boot(); | 246 | fastboot_boot(); |
244 | net_set_state(NETLOOP_SUCCESS); | 247 | net_set_state(NETLOOP_SUCCESS); |
245 | } | 248 | } |
246 | 249 | ||
247 | /** | 250 | /** |
248 | * fastboot_handler() - Incoming UDP packet handler. | 251 | * fastboot_handler() - Incoming UDP packet handler. |
249 | * | 252 | * |
250 | * @packet: Pointer to incoming UDP packet | 253 | * @packet: Pointer to incoming UDP packet |
251 | * @dport: Destination UDP port | 254 | * @dport: Destination UDP port |
252 | * @sip: Source IP address | 255 | * @sip: Source IP address |
253 | * @sport: Source UDP port | 256 | * @sport: Source UDP port |
254 | * @len: Packet length | 257 | * @len: Packet length |
255 | */ | 258 | */ |
256 | static void fastboot_handler(uchar *packet, unsigned int dport, | 259 | static void fastboot_handler(uchar *packet, unsigned int dport, |
257 | struct in_addr sip, unsigned int sport, | 260 | struct in_addr sip, unsigned int sport, |
258 | unsigned int len) | 261 | unsigned int len) |
259 | { | 262 | { |
260 | struct fastboot_header header; | 263 | struct fastboot_header header; |
261 | char fastboot_data[DATA_SIZE] = {0}; | 264 | char fastboot_data[DATA_SIZE] = {0}; |
262 | unsigned int fastboot_data_len = 0; | 265 | unsigned int fastboot_data_len = 0; |
263 | 266 | ||
264 | if (dport != fastboot_our_port) | 267 | if (dport != fastboot_our_port) |
265 | return; | 268 | return; |
266 | 269 | ||
267 | fastboot_remote_ip = sip; | 270 | fastboot_remote_ip = sip; |
268 | fastboot_remote_port = sport; | 271 | fastboot_remote_port = sport; |
269 | 272 | ||
270 | if (len < sizeof(struct fastboot_header) || len > PACKET_SIZE) | 273 | if (len < sizeof(struct fastboot_header) || len > PACKET_SIZE) |
271 | return; | 274 | return; |
272 | memcpy(&header, packet, sizeof(header)); | 275 | memcpy(&header, packet, sizeof(header)); |
273 | header.flags = 0; | 276 | header.flags = 0; |
274 | header.seq = ntohs(header.seq); | 277 | header.seq = ntohs(header.seq); |
275 | packet += sizeof(header); | 278 | packet += sizeof(header); |
276 | len -= sizeof(header); | 279 | len -= sizeof(header); |
277 | 280 | ||
278 | switch (header.id) { | 281 | switch (header.id) { |
279 | case FASTBOOT_QUERY: | 282 | case FASTBOOT_QUERY: |
280 | fastboot_send(header, fastboot_data, 0, 0); | 283 | fastboot_send(header, fastboot_data, 0, 0); |
281 | break; | 284 | break; |
282 | case FASTBOOT_INIT: | 285 | case FASTBOOT_INIT: |
283 | case FASTBOOT_FASTBOOT: | 286 | case FASTBOOT_FASTBOOT: |
284 | fastboot_data_len = len; | 287 | fastboot_data_len = len; |
285 | if (len > 0) | 288 | if (len > 0) |
286 | memcpy(fastboot_data, packet, len); | 289 | memcpy(fastboot_data, packet, len); |
287 | if (header.seq == sequence_number) { | 290 | if (header.seq == sequence_number) { |
288 | fastboot_send(header, fastboot_data, | 291 | fastboot_send(header, fastboot_data, |
289 | fastboot_data_len, 0); | 292 | fastboot_data_len, 0); |
290 | sequence_number++; | 293 | sequence_number++; |
291 | } else if (header.seq == sequence_number - 1) { | 294 | } else if (header.seq == sequence_number - 1) { |
292 | /* Retransmit last sent packet */ | 295 | /* Retransmit last sent packet */ |
293 | fastboot_send(header, fastboot_data, | 296 | fastboot_send(header, fastboot_data, |
294 | fastboot_data_len, 1); | 297 | fastboot_data_len, 1); |
295 | } | 298 | } |
296 | break; | 299 | break; |
297 | default: | 300 | default: |
298 | pr_err("ID %d not implemented.\n", header.id); | 301 | pr_err("ID %d not implemented.\n", header.id); |
299 | header.id = FASTBOOT_ERROR; | 302 | header.id = FASTBOOT_ERROR; |
300 | fastboot_send(header, fastboot_data, 0, 0); | 303 | fastboot_send(header, fastboot_data, 0, 0); |
301 | break; | 304 | break; |
302 | } | 305 | } |
303 | } | 306 | } |
304 | 307 | ||
305 | void fastboot_start_server(void) | 308 | void fastboot_start_server(void) |
306 | { | 309 | { |
307 | printf("Using %s device\n", eth_get_name()); | 310 | printf("Using %s device\n", eth_get_name()); |
308 | printf("Listening for fastboot command on %pI4\n", &net_ip); | 311 | printf("Listening for fastboot command on %pI4\n", &net_ip); |
309 | 312 | ||
310 | fastboot_our_port = WELL_KNOWN_PORT; | 313 | fastboot_our_port = WELL_KNOWN_PORT; |
311 | 314 | ||
312 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) | 315 | #if CONFIG_IS_ENABLED(FASTBOOT_FLASH) |
313 | fastboot_set_progress_callback(fastboot_timed_send_info); | 316 | fastboot_set_progress_callback(fastboot_timed_send_info); |
314 | #endif | 317 | #endif |
315 | net_set_udp_handler(fastboot_handler); | 318 | net_set_udp_handler(fastboot_handler); |
316 | 319 | ||
317 | /* zero out server ether in case the server ip has changed */ | 320 | /* zero out server ether in case the server ip has changed */ |
318 | memset(net_server_ethaddr, 0, 6); | 321 | memset(net_server_ethaddr, 0, 6); |
319 | } | 322 | } |
320 | 323 |