Commit d0f64bb8286739f9efd656cd2d63539106427f80
1 parent
2b5a5ccffc
Exists in
smarc_8mq-imx_v2020.04_5.4.24_2.1.0
and in
1 other branch
MA-17159 Implement bootloader menu for imx7ulp
According to the spec of android wear, the device MUST provides a bootloader menu for debugging purpose. This commit implements a simple bootloader menu based on imx7ulp_evk revb board, the menu will show when booting with 'VOL+' key pressed, users can press "VOL+" to choose the item, then press "ONOFF" key to confirm. Test: bootloader menu show on imx7ulp_evk revb. Change-Id: I80638a43afa17e312e633b05888c62440380b42b Signed-off-by: Ji Luo <ji.luo@nxp.com>
Showing 2 changed files with 115 additions and 1 deletions Side-by-side Diff
board/freescale/mx7ulp_evk/mx7ulp_evk.c
... | ... | @@ -14,6 +14,14 @@ |
14 | 14 | #include <usb.h> |
15 | 15 | #include <dm.h> |
16 | 16 | |
17 | +#ifdef CONFIG_BOOTLOADER_MENU | |
18 | +#include "video.h" | |
19 | +#include "dm/uclass.h" | |
20 | +#include "video_font_data.h" | |
21 | +#include "video_console.h" | |
22 | +#include "recovery.h" | |
23 | +#endif | |
24 | + | |
17 | 25 | DECLARE_GLOBAL_DATA_PTR; |
18 | 26 | |
19 | 27 | #define UART_PAD_CTRL (PAD_CTL_PUS_UP) |
... | ... | @@ -136,6 +144,15 @@ |
136 | 144 | } |
137 | 145 | #endif |
138 | 146 | |
147 | +#ifdef CONFIG_BOOTLOADER_MENU | |
148 | +static iomux_cfg_t const vol_pad[] = { | |
149 | + MX7ULP_PAD_PTA3__PTA3 | MUX_PAD_CTRL(PAD_CTL_IBE_ENABLE), | |
150 | +}; | |
151 | +#define VOLP_GPIO IMX_GPIO_NR(1, 3) | |
152 | +bool is_vol_key_pressed(void); | |
153 | +int show_bootloader_menu(void); | |
154 | +#endif | |
155 | + | |
139 | 156 | int board_late_init(void) |
140 | 157 | { |
141 | 158 | env_set("tee", "no"); |
... | ... | @@ -147,6 +164,16 @@ |
147 | 164 | board_late_mmc_env_init(); |
148 | 165 | #endif |
149 | 166 | |
167 | +#ifdef CONFIG_BOOTLOADER_MENU | |
168 | + mx7ulp_iomux_setup_multiple_pads(vol_pad, ARRAY_SIZE(vol_pad)); | |
169 | + if (gpio_request(VOLP_GPIO, "volp")) | |
170 | + printf("request error\n"); | |
171 | + gpio_direction_input(VOLP_GPIO); | |
172 | + | |
173 | + if (is_vol_key_pressed()) | |
174 | + show_bootloader_menu(); | |
175 | +#endif | |
176 | + | |
150 | 177 | return 0; |
151 | 178 | } |
152 | 179 | |
... | ... | @@ -164,5 +191,87 @@ |
164 | 191 | /* the onoff button is 'pressed' by default on evk board */ |
165 | 192 | return (bool)(!(readl(SNVS_HPSR_REVB) & (0x1 << 6))); |
166 | 193 | } |
167 | -#endif | |
194 | + | |
195 | +#ifdef CONFIG_BOOTLOADER_MENU | |
196 | +char bootloader_menu[4][40] = { | |
197 | + " * Power off the device\n", | |
198 | + " * Start the device normally\n", | |
199 | + " * Restart the bootloader\n", | |
200 | + " * Boot into recovery mode\n" | |
201 | +}; | |
202 | + | |
203 | +bool is_vol_key_pressed(void) { | |
204 | + int ret = 0; | |
205 | + ret = gpio_get_value(VOLP_GPIO); | |
206 | + return (bool)(!!ret); | |
207 | +} | |
208 | + | |
209 | +int show_bootloader_menu(void) { | |
210 | + struct udevice *dev, *dev_console; | |
211 | + uint32_t focus = 0, i; | |
212 | + bool stop_menu = false; | |
213 | + | |
214 | + /* clear screen first */ | |
215 | + if (uclass_first_device_err(UCLASS_VIDEO, &dev)) { | |
216 | + printf("no video device found!\n"); | |
217 | + return -1; | |
218 | + } | |
219 | + video_clear(dev); | |
220 | + | |
221 | + if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev_console)) { | |
222 | + printf("no text console device found!\n"); | |
223 | + return -1; | |
224 | + } | |
225 | + | |
226 | + vidconsole_position_cursor(dev_console, 0, 1); | |
227 | + vidconsole_put_string(dev_console, "Press 'vol+' to choose an item, press\n"); | |
228 | + vidconsole_put_string(dev_console, "power key to confirm:\n"); | |
229 | + while (!stop_menu) { | |
230 | + /* reset the cursor position. */ | |
231 | + vidconsole_position_cursor(dev_console, 0, 4); | |
232 | + /* show menu */ | |
233 | + for (i = 0; i < 4; i++) { | |
234 | + /* reverse color for the 'focus' line. */ | |
235 | + if (i == focus) | |
236 | + vidconsole_put_string(dev_console, "\x1b[7m"); | |
237 | + /* show text */ | |
238 | + vidconsole_put_string(dev_console, bootloader_menu[i]); | |
239 | + /* reset color back for the 'next' line. */ | |
240 | + if (i == focus) | |
241 | + vidconsole_put_string(dev_console, "\x1b[0m"); | |
242 | + } | |
243 | + /* check button status */ | |
244 | + while (1) { | |
245 | + if (is_power_key_pressed()) { | |
246 | + switch (focus) { | |
247 | + case 0: /*TODO*/ | |
248 | + case 1: | |
249 | + break; | |
250 | + case 2: | |
251 | + do_reset(NULL, 0, 0, NULL); | |
252 | + case 3: | |
253 | + board_recovery_setup(); | |
254 | + break; | |
255 | + default: | |
256 | + break; | |
257 | + } | |
258 | + stop_menu = true; | |
259 | + break; | |
260 | + } else if (is_vol_key_pressed()) { | |
261 | + focus++; | |
262 | + printf("\nfocus is %d\n", focus); | |
263 | + if (focus > 3) | |
264 | + focus = 0; | |
265 | + mdelay(400); | |
266 | + break; | |
267 | + } | |
268 | + } | |
269 | + } | |
270 | + | |
271 | + /* clear screen before exit */ | |
272 | + video_clear(dev); | |
273 | + return 0; | |
274 | +} | |
275 | +#endif /* CONFIG_BOOTLOADER_MENU */ | |
276 | +#endif /* CONFIG_ANDROID_SUPPORT*/ |
lib/Kconfig
... | ... | @@ -358,6 +358,11 @@ |
358 | 358 | help |
359 | 359 | The time of avb warning logo will last (s). |
360 | 360 | |
361 | +config BOOTLOADER_MENU | |
362 | + bool "Enable bootloader menu for android device" | |
363 | + help | |
364 | + bootloader menu feature for android device. | |
365 | + | |
361 | 366 | config APPEND_BOOTARGS |
362 | 367 | bool "Append bootargs support" |
363 | 368 |