MA-17159 Implement bootloader menu for imx7ulp
authorJi Luo <ji.luo@nxp.com>
Thu, 7 May 2020 04:52:00 +0000 (12:52 +0800)
committerJi Luo <ji.luo@nxp.com>
Thu, 13 May 2021 01:49:19 +0000 (09:49 +0800)
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>
(cherry picked from commit 9d5995caf7146d4955fba2524a7f25d761049e28)

arch/arm/mach-imx/Kconfig
board/freescale/mx7ulp_evk/mx7ulp_evk.c

index 33c8f9a..d46437a 100644 (file)
@@ -335,3 +335,8 @@ config ANDROID_DYNAMIC_PARTITION
 config VIRTUAL_AB_SUPPORT
        bool "Support virtual AB update"
        select ANDROID_DYNAMIC_PARTITION
+
+config BOOTLOADER_MENU
+       bool "Enable bootloader menu for android device"
+       help
+       bootloader menu feature for android device.
index ce71675..9887aee 100644 (file)
 #include <dm.h>
 #include <env.h>
 
+#ifdef CONFIG_BOOTLOADER_MENU
+#include "video.h"
+#include "dm/uclass.h"
+#include "video_font_data.h"
+#include "video_console.h"
+#include "recovery.h"
+#endif
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #define UART_PAD_CTRL  (PAD_CTL_PUS_UP)
@@ -145,6 +153,15 @@ add:
 }
 #endif
 
+#ifdef CONFIG_BOOTLOADER_MENU
+static iomux_cfg_t const vol_pad[] = {
+       MX7ULP_PAD_PTA3__PTA3 | MUX_PAD_CTRL(PAD_CTL_IBE_ENABLE),
+};
+#define VOLP_GPIO      IMX_GPIO_NR(1, 3)
+bool is_vol_key_pressed(void);
+int show_bootloader_menu(void);
+#endif
+
 int board_late_init(void)
 {
        env_set("tee", "no");
@@ -156,6 +173,16 @@ int board_late_init(void)
        board_late_mmc_env_init();
 #endif
 
+#ifdef CONFIG_BOOTLOADER_MENU
+       mx7ulp_iomux_setup_multiple_pads(vol_pad, ARRAY_SIZE(vol_pad));
+       if (gpio_request(VOLP_GPIO, "volp"))
+               printf("request error\n");
+       gpio_direction_input(VOLP_GPIO);
+
+       if (is_vol_key_pressed())
+               show_bootloader_menu();
+#endif
+
        return 0;
 }
 
@@ -164,4 +191,85 @@ bool is_power_key_pressed(void) {
        /* the onoff button is 'pressed' by default on evk board */
        return (bool)(!(readl(SNVS_HPSR_REVB) & (0x1 << 6)));
 }
-#endif
+
+#ifdef CONFIG_BOOTLOADER_MENU
+char bootloader_menu[4][40] = {
+       "   * Power off the device\n",
+       "   * Start the device normally\n",
+       "   * Restart the bootloader\n",
+       "   * Boot into recovery mode\n"
+};
+
+bool is_vol_key_pressed(void) {
+       int ret = 0;
+       ret = gpio_get_value(VOLP_GPIO);
+       return (bool)(!!ret);
+}
+
+int show_bootloader_menu(void) {
+       struct udevice *dev, *dev_console;
+       uint32_t focus = 0, i;
+       bool stop_menu = false;
+
+       /* clear screen first */
+       if (uclass_first_device_err(UCLASS_VIDEO, &dev)) {
+               printf("no video device found!\n");
+               return -1;
+       }
+       video_clear(dev);
+
+       if (uclass_first_device_err(UCLASS_VIDEO_CONSOLE, &dev_console)) {
+               printf("no text console device found!\n");
+               return -1;
+       }
+
+       vidconsole_position_cursor(dev_console, 0, 1);
+       vidconsole_put_string(dev_console, "Press 'vol+' to choose an item, press\n");
+       vidconsole_put_string(dev_console, "power key to confirm:\n");
+       while (!stop_menu) {
+               /* reset the cursor position. */
+               vidconsole_position_cursor(dev_console, 0, 4);
+               /* show menu */
+               for (i = 0; i < 4; i++) {
+                       /* reverse color for the 'focus' line. */
+                       if (i == focus)
+                               vidconsole_put_string(dev_console, "\x1b[7m");
+                       /* show text */
+                       vidconsole_put_string(dev_console, bootloader_menu[i]);
+                       /* reset color back for the 'next' line. */
+                       if (i == focus)
+                               vidconsole_put_string(dev_console, "\x1b[0m");
+               }
+               /* check button status */
+               while (1) {
+                       if (is_power_key_pressed()) {
+                               switch (focus) {
+                                       case 0: /*TODO*/
+                                       case 1:
+                                               break;
+                                       case 2:
+                                               do_reset(NULL, 0, 0, NULL);
+                                       case 3:
+                                               board_recovery_setup();
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               stop_menu = true;
+                               break;
+                       } else if (is_vol_key_pressed()) {
+                               focus++;
+                               if (focus > 3)
+                                       focus = 0;
+                               mdelay(400);
+                               break;
+                       }
+               }
+       }
+
+       /* clear screen before exit */
+       video_clear(dev);
+       return 0;
+}
+#endif /* CONFIG_BOOTLOADER_MENU */
+#endif /* CONFIG_ANDROID_SUPPORT*/