From 631abc02c245c2ad0f286dfe5bc2e303aed3316e Mon Sep 17 00:00:00 2001 From: retro98boy Date: Mon, 9 Mar 2026 05:20:20 +0800 Subject: [PATCH] CAINIAO CNIoT-CORE: U-Boot: Add a method to prioritize booting from USB drive via the power button --- .../add-board-cainiao-cniot-core.patch | 181 +++++++++++++++++- 1 file changed, 178 insertions(+), 3 deletions(-) diff --git a/patch/u-boot/v2026.01/board_cainiao-cniot-core/add-board-cainiao-cniot-core.patch b/patch/u-boot/v2026.01/board_cainiao-cniot-core/add-board-cainiao-cniot-core.patch index bd4f62e618..131e6ebb2d 100644 --- a/patch/u-boot/v2026.01/board_cainiao-cniot-core/add-board-cainiao-cniot-core.patch +++ b/patch/u-boot/v2026.01/board_cainiao-cniot-core/add-board-cainiao-cniot-core.patch @@ -11,15 +11,190 @@ index 00000000..236f2468 + */ + +#include "meson-g12-common-u-boot.dtsi" +diff --git a/board/amlogic/cniot-core/Makefile b/board/amlogic/cniot-core/Makefile +new file mode 100644 +index 00000000..c4135658 +--- /dev/null ++++ b/board/amlogic/cniot-core/Makefile +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: GPL-2.0+ ++# ++# Author: retro98boy ++ ++obj-y := cniot-core.o +diff --git a/board/amlogic/cniot-core/cniot-core.c b/board/amlogic/cniot-core/cniot-core.c +new file mode 100644 +index 00000000..325e39f9 +--- /dev/null ++++ b/board/amlogic/cniot-core/cniot-core.c +@@ -0,0 +1,158 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Author: retro98boy ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct gpio_desc pwrbtn_gpio[1] = { 0 }; ++static bool pwrbtn_valid = false; ++ ++static int request_gpios(void) ++{ ++ int node = -1; ++ int rc = -1; ++ ++ node = fdt_path_offset(gd->fdt_blob, "/gpio-keys-polled/pwr-btn"); ++ if (node < 0) ++ return -ENODEV; ++ ++ rc = gpio_request_list_by_name_nodev(offset_to_ofnode(node), "gpios", ++ pwrbtn_gpio, ++ ARRAY_SIZE(pwrbtn_gpio), ++ GPIOD_IS_IN); ++ if (rc < 0) ++ return -ENODEV; ++ ++ pwrbtn_valid = true; ++ ++ return 0; ++} ++ ++static void free_gpios(void) ++{ ++ if (pwrbtn_valid) { ++ gpio_free_list_nodev(pwrbtn_gpio, ARRAY_SIZE(pwrbtn_gpio)); ++ pwrbtn_valid = false; ++ } ++} ++ ++static bool is_pwrbtn_really_released(void) ++{ ++ const int check_ms = 300; ++ const int step_ms = 50; ++ ++ for (int i = 0; i < check_ms / step_ms; i++) { ++ mdelay(step_ms); ++ if (dm_gpio_get_value(&pwrbtn_gpio[0]) == 1) ++ return false; ++ } ++ ++ return true; ++} ++ ++/* ++ * The UART pads on this device are deeply recessed, ++ * and disassembling the hardware is a major hassle. ++ * Once U-Boot and the OS are installed on the eMMC, ++ * rescuing data or recovering the system becomes difficult ++ * if a failure occurs (such as a kernel panic or rootfs corruption), ++ * because U-Boot prioritizes booting from eMMC over USB. ++ * To address this, here is a workaround: ++ * by holding the power button for 5 seconds during boot-up, ++ * U-Boot will be forced to retain only the USB boot target. ++ * This prevents U-Boot from loading a corrupted kernel image from the eMMC ++ * and getting stuck in a boot loop. Additionally, ++ * it is recommended that the OS image flashed to the USB drive ++ * be different from the one on the eMMC to avoid partition UUID conflicts. ++ */ ++static void handle_usb_boot_detection(void) ++{ ++ const int target_seconds = 5; ++ ulong start_time = get_timer(0); ++ ulong last_print_time = 0; ++ ++ printf("Check USB boot: Hold Power Button for %ds\n", target_seconds); ++ ++ while (get_timer(start_time) < (target_seconds * 1000)) { ++ if (dm_gpio_get_value(&pwrbtn_gpio[0]) == 0) { ++ if (is_pwrbtn_really_released()) { ++ printf("[Normal Boot] Button released early.\n"); ++ return; ++ } ++ } ++ ++ ulong current_elapsed = get_timer(start_time) / 1000; ++ if (current_elapsed > last_print_time) { ++ /* ++ * It would be even better if this device had an integrated LED. ++ * We could toggle the LED status here as a visual indicator. ++ */ ++ printf("Power button holding... %ld/%ds\r", ++ current_elapsed, target_seconds); ++ last_print_time = current_elapsed; ++ } ++ ++ mdelay(10); ++ } ++ ++ printf("\n[USB Boot] Trigger matched!\n"); ++ env_set("boot_targets", "usb0"); ++ ++ /* ++ * We must wait for the user to release the power button ++ * before proceeding with the kernel boot. ++ * Otherwise, an extended press (since the user cannot perceive the boot progress) ++ * might trigger a reset once the kernel is running. ++ * A timeout should also be implemented: ++ * if the button is stuck due to hardware damage, ++ * the system shouldn't hang in U-Boot indefinitely. ++ * This is crucial because U-Boot is fixed in eMMC, ++ * whereas the kernel and DTB are easily modifiable on a USB drive, ++ * making it simpler to disable the power button later if needed. ++ */ ++ const ulong release_timeout_ms = 30000; ++ ulong release_start = get_timer(0); ++ while (!is_pwrbtn_really_released()) { ++ if (get_timer(release_start) > release_timeout_ms) { ++ printf("\nRelease timeout reached. Continuing boot.\n"); ++ break; ++ } ++ printf("Waiting for button release to continue...\r"); ++ } ++ ++ printf("\nButton released safely. Proceeding...\n"); ++} ++ ++int misc_init_r(void) ++{ ++ meson_generate_serial_ethaddr(); ++ ++ return 0; ++} ++ ++int meson_board_late_init(void) ++{ ++#if defined(CONFIG_WATCHDOG) ++ printf("Watchdog set, skip USB boot detection.\n"); ++ return 0; ++#else ++ if (request_gpios()) { ++ printf("Failed to request gpios for USB boot detection.\n"); ++ return 0; ++ } ++ ++ handle_usb_boot_detection(); ++ free_gpios(); ++ ++ return 0; ++#endif ++} diff --git a/configs/cainiao-cniot-core_defconfig b/configs/cainiao-cniot-core_defconfig new file mode 100644 -index 00000000..0ee30015 +index 00000000..27000ab4 --- /dev/null +++ b/configs/cainiao-cniot-core_defconfig @@ -0,0 +1,110 @@ +# Reference from khadas-vim3_defconfig +CONFIG_ARM=y -+CONFIG_SYS_BOARD="w400" ++CONFIG_SYS_BOARD="cniot-core" +CONFIG_ARCH_MESON=y +CONFIG_TEXT_BASE=0x01000000 +CONFIG_NR_DRAM_BANKS=1 @@ -129,7 +304,7 @@ index 00000000..0ee30015 +CONFIG_ZSTD=y diff --git a/dts/upstream/src/arm64/amlogic/meson-g12b-a311d-cainiao-cniot-core.dts b/dts/upstream/src/arm64/amlogic/meson-g12b-a311d-cainiao-cniot-core.dts new file mode 100644 -index 00000000..09b1bbac +index 00000000..85ea1c4a --- /dev/null +++ b/dts/upstream/src/arm64/amlogic/meson-g12b-a311d-cainiao-cniot-core.dts @@ -0,0 +1,600 @@