summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2026-02-25board: samsung: exynos-mobile: add EFI capsule update supportKaustabh Chakraborty
Add support for EFI capsule updates via U-Boot's DFU. This flashes the boot partition with the new image provided in the capsule. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-25board: samsung: exynos-mobile: use blkmap for booting from userdata ↵Kaustabh Chakraborty
subpartitions Some distributions tend to provide a single combined image with EFS and the system root filesystem. Flashing it as-is in a single partition (usually done in userdata partition as it is the largest) is not bootable as U-Boot does not understand subpartitions. Use blkmap to map the userdata partition into its own block device. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-25phy: samsung: add support for exynos7870 USB PHYKaustabh Chakraborty
The USB PHY used by the Exynos7870 SoC has a single USB 2.0 interface. Add its dedicated variant enum, compatible, and init/exit functions. The PHY enable bit of Exynos7870's PHY is different in contrast to that of Exynos850 and most Exynos PHYs. To allow this change, a simple if condition is added in exynos_usbdrd_phy_isol() which changes the bitmask. Since the variant enum is required, the function argument is changed to accept the driver data itself. Reviewed-by: Mattijs Korpershoek <[email protected]> Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-25phy: samsung: add enum for variants based on SoCsKaustabh Chakraborty
The variant enum is used to uniquely identify which SoC the PHY block belongs to. It is initially set in the match table, along with the compatible string, it gets copied to driver data struct during probe. SoC specific functions must only be called if the respective variant enum is set. Add switch-case blocks wherever required. Reviewed-by: Mattijs Korpershoek <[email protected]> Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-24ARM: stm32mp: Check secure state firstGatien Chevallier
Secure state must be checked before handling semaphores, otherwise it can cause an IAC. Signed-off-by: Gatien Chevallier <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24ARM: stm32mp: Fix CID and semaphore checkGatien Chevallier
Peripheral holding CID0 cannot be accessed, remove this completely incorrect check. While there, fix and simplify the semaphore checking that should be performed when the CID filtering is enabled. Signed-off-by: Gatien Chevallier <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24ARM: stm32mp: Do not acquire RIFSC semaphore if CID filtering is disabledGatien Chevallier
If the CID filtering is enabled, the semaphore mode is disabled as well. To avoid an incorrect behavior and error trace, add a check of CID filtering state before acquiring the semaphore. Signed-off-by: Gatien Chevallier <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24configs: stm32mp25: Enable CMD_STM32KEYPatrice Chotard
Enable CONFIG_CMD_STM32KEY flag to enable usage of command stm32key. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: cmd_stm32key: add support of ADAC public key hashThomas Bourgoin
Add support of ADAC-PKH for STM32MP21. Signed-off-by: Thomas Bourgoin <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: cmd_stm32key: add support of remoteproc firmware public keyGwenael Treuveur
Add support of RPROC-FW-PKH for STM32MP25, STM32MP23 and STM32MP21. Signed-off-by: Gwenael Treuveur <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: cmd_stm32key: add support of remoteproc firmware encryption keyThomas Bourgoin
Add support of RPROC-FW-KEY for STM32MP25, STM32MP23 and STM32MP21. Signed-off-by: Thomas Bourgoin <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: cmd_stm32key: add support of OTP key format 2Thomas Bourgoin
Add support of OTP key format 2 used by OP-TEE. Key formats are describes in the STM32MPUs references manuals section OTP mapping. Signed-off-by: Thomas Bourgoin <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: cmd_stm32key: add support of STM32MP21x SoCThomas Bourgoin
Update stm32key to support stm32mp21 OTP mapping. Create a new list of key to support the following differences : - STM32MP21x SoC support 128b and 25b FSBL encryption keys. - OEM-KEY1 and OEM-KEY2 used for authentication are in different OTP from STM32MP25 and STM32MP23. stm32key is compatible with platform STM32MP2 (aarch64) Hence, use unsigned long to handle argument addr of function read_key_value() instead of u32. Signed-off-by: Thomas Bourgoin <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp1: Add check on syscon_get_first_range() return valuePatrice Chotard
syscon_get_first_range()'s return value is used as base address to perform a read, without any checks. In case stmp32mp_syscon is not binded, syscon_get_first_range() returns -ENODEV which leads to a "Synchronous abort". Add syscon_get_first_range() check on return value. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp2: Add check on syscon_get_first_range() return valuePatrice Chotard
syscon_get_first_range()'s return value is used as base address to perform a read, without any checks. In case stmp32mp_syscon is not binded, syscon_get_first_range() returns -ENODEV which leads to a "Synchronous abort". Add syscon_get_first_range() check on return value. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp2: Migrate duplicated code into stm32mp2x.cPatrice Chotard
Same code is duplicated into stm32mp25x.c, stm32mp23x.c and stm32mp21x.c. Migrate read_deviceid(), get_cpu_dev(), get_cpu_rev(), get_cpu_type() and get_cpu_package() into new stm32mp2x.c. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24ARM: dts: stm32: Add bootph-all in stm32mp215f-dk-u-boot.dtsiPatrice Chotard
Add temporarily bootph-all property in usart2 and syscfg nodes to allows stm32mp215f-dk board to boot. When DT kernel series [1] will be merged and synchronized in U-Boot this patch will be reverted. [1] https://lore.kernel.org/linux-arm-kernel/[email protected]/ Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24ARM: dts: stm32: Add stm32mp215f-dk-u-bootPatrice Chotard
Add U-Boot specific file for stm32mp215f-dk board Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24ARM: stm32mp: Add STM32MP21 supportPatrice Chotard
STM32MP21 application processors (STM32 MPUs) based on a single Arm Cortex®-A35 core running up to 1.5 GHz and Cortex®-M33 core running at 300 MHz. It is pin-compatible with the STM32MP2 series in the VFBGA361 10×10 mm package: the STM32MP21 uses a subset of the STM32MP23 pinout, which itself is a subset of the STM32MP25. More details available here : https://www.st.com/en/microcontrollers-microprocessors/stm32mp2-series.html Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: cmd_stm32key: add support of STM32MP21xPatrice Chotard
Add cmd_stm32key support for STM32MP21x SoCs family. Signed-off-by: Yann Gautier <[email protected]> Signed-off-by: Nicolas Le Bayon <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: syscon: Add STM32MP21 supportPatrice Chotard
Add "st,stm32mp21-syscfg" compatible. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24reset: stm32mp21: add stm32mp21 reset driverPatrice Chotard
Implement STM32MP21 reset drivers using stm32-core-reset API. Signed-off-by: Gabriel Fernandez <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24clk: stm32mp21: Add clock driver supportPatrice Chotard
Add clock driver support for STM32MP21 SoCs. Signed-off-by: Nicolas Le Bayon <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24boot: fit: validate FDT/DTO payload before fdt_open_into()James Hilliard
boot_get_fdt_fit_into_buffer() calls fdt_open_into() for both the base FDT and overlay DTO blobs loaded from a FIT image. Those blobs come from FIT payload data. In the overlay path, fit_image_load() is called with FIT_LOAD_IGNORED, so the IH_TYPE_FLATDT header check in fit_image_load() is skipped. This leaves fdt_open_into() to consume header-derived offsets/sizes from unvalidated input. Validate the full blob against the payload length first with fdt_check_full(fdtsrcbuf, srclen), then proceed with fdt_totalsize() and fdt_open_into(). This fixes Coverity CID 644638 (TAINTED_SCALAR). Fixes: 5ebf0c55a23 ("image: fit: Apply overlays using aligned writable FDT copies") Link: https://lore.kernel.org/all/20260223195109.GG3233182@bill-the-cat/ Signed-off-by: James Hilliard <[email protected]> Reviewed-by: Tom Rini <[email protected]>
2026-02-24arm: mach-k3: common: Clamp RAM end address to board-usable region in ↵Devarsh Thakkar
spl_enable_cache() commit ba20b2443c29 ("arm: mach-k3: common: Reserve video memory from end of the RAM") switched spl_enable_cache() to use gd->ram_top directly but omitted the board_get_usable_ram_top() call that limits RAM configuration and provides updated RAM end address per memory map used by board and impacts subsequent allocations and reservations. For e.g. here it impacts how high the TLB may be placed. On Verdin AM62 (512 MiB), the raw end of RAM (0xA0000000) is inside OP-TEE's region. board_get_usable_ram_top() in verdin-am62.c returns 0x9C000000 to keep relocations below it, but spl_enable_cache() never called it. commit 42b3ee7fa524 ("arm: mach-k3: am62x: Enable memory firewall support") then enforced the OP-TEE firewall, turning the silent corruption into a hard hang. Fix by calling board_get_usable_ram_top() after computing raw ram_top, consistent with setup_dest_addr() in board_f.c. A weak default is provided for boards that do not need to restrict the RAM top. Fixes: ba20b2443c29 ("arm: mach-k3: common: Reserve video memory from end of the RAM") Reported-by: Francesco Dolcini <[email protected]> Link: https://lore.kernel.org/all/20260224102121.GB340942@francesco-nb/ Signed-off-by: Devarsh Thakkar <[email protected]> Tested-by: Francesco Dolcini <[email protected]> # Verdin AM62 512MB
2026-02-24arm: armv8: Flush TLB before enabling MMUMark Kettenis
Commit 9ebdbbc43e5f ("arm: armv8: invalidate dcache entries on dcache_enable") broke Apple Silicon machines in certain scenarios. If the MMU is currently not enabled we need to flush the TLB before we enable it to prevent stale TLB entries from becoming active again. So move the __asm_invalidate_tlb_all() back immediately before the mmu_setup() call. Fixes: 9ebdbbc43e5f ("arm: armv8: invalidate dcache entries on dcache_enable") Signed-off-by: Mark Kettenis <[email protected]> Reviewed-by: Ilias Apalodimas <[email protected]>
2026-02-24board: st: common: add uclass_get_device_by_driver()'s return value checkPatrice Chotard
class_get_device_by_driver()'s return value is not checked, in case of BSEC driver is not probed, dev is not set and used just after as parameter of misc_read() which leads to a Synchronous Abort. Add uclass_get_device_by_driver()'s return value check to fix it. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24board: st: common: Add support of stm32mp21xx-dk boardPatrice Chotard
Add board identifier for STM32MP21 discovery board = MB2059. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp2: Update size of DDR entry in MMU tablePatrice Chotard
On 1GB board, in particular cases, a prefetch operation is done just above the 1GB boundary. The DDR size is 1GB (0x80000000 to 0xc0000000), there is an access on 0xc00017c0 (ie 0x800017c0). As beginning of DDR is protected by MMU until CONFIG_TEXT_BASE (0x80000000 to 0x84000000), it triggers the following IAC: E/TC:0 stm32_iac_itr:192 IAC exceptions [159:128]: 0x200 E/TC:0 stm32_iac_itr:197 IAC exception ID: 137 I/TC: DUMPING DATA FOR risaf@420d0000 I/TC: ===================================================== I/TC: Status register (IAESR0): 0x11 I/TC: ----------------------------------------------------- I/TC: Faulty address (IADDR0): 0xc00017c0 I/TC: ===================================================== E/TC:0 Panic at /usr/src/debug/optee-os-stm32mp/4.0.0-gitvalid.8> E/TC:0 TEE load address @ 0x82000000 E/TC:0 Call stack: E/TC:0 0x82007f30 E/TC:0 0x820444b4 E/TC:0 0x8202dc54 E/TC:0 0x82041fe0 E/TC:0 0x820143b8 By default, in MMU table, the DDR size is set to 4GB, but not all STM32MP2 based board embeds 4GB, some has only 1 or 2GB of DDR. The MMU table entry dedicated to DDR need to be updated with the real DDR size previously read from DT. After relocation, in enable_caches(), update the MMU table between the dcache_disable() / dcache_enable() with the real DDR size. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: fix array bounds checksPatrice Chotard
Fix index check against array size. If that index is equal to the array size, we'll access one-past-the-end of the array. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24stm32mp: stm32prog: Remove fsbl_nor_detected from stm32prog_data structPatrice Chotard
No more need to test if a fsbl partition is present on NOR when booting from serial or USB. Now MTD devices are automatically populated with partition information found in DT. Remove fsbl_nor_detected boolean from stm32prog_data struct and all code using it. Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24pinctrl: pinctrl_stm32: prevent the use of the secure protected pinsFabien Dessenne
The hardware denies any access from the U-Boot non-secure world to the secure-protected pins. Hence, prevent any driver to configure such a pin. Identify the secure pins with "NO ACCESS" through the 'pinmux status -a' command. Use a driver data structure to identify which hardware versions support this feature. Signed-off-by: Fabien Dessenne <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-24gpio: stm32-gpio: prevent the use of the secure protected pinsFabien Dessenne
The hardware denies any access from the U-Boot non-secure world to the secure-protected pins. Hence, prevent any driver to request such a pin. Signed-off-by: Fabien Dessenne <[email protected]> Signed-off-by: Patrice Chotard <[email protected]> Reviewed-by: Patrick Delaunay <[email protected]>
2026-02-23board: Correct usage of fdtfile=CONFIG_DEFAULT_FDT_FILETom Rini
As explained in commit 03d2d5fc003f ("board: sifive: unmatched: set fdtfile with unquoted variable.") using the syntax of 'fdtfile=CONFIG_DEFAULT_FDT_FILE' in the plain text environment files will lead to extraneous and problematic "s in the output. This is fixed by using fdtfile=DEFAULT_FDT_FILE which was introduced recently. Acked-by: Peng Fan <[email protected]> Signed-off-by: Tom Rini <[email protected]>
2026-02-23Merge patch series "net: mdio-mt7531-mmio: consolidate and improve probe"Tom Rini
Christian Marangi <[email protected]> says: This small series consolidate header usage of mdio-mt7531-mmio driver and improve usage in preparation for support of OF PHY autoprobe. This driver is still not used (as it will be used by AN7581/AN7583) in the OF mode (it's used by MT7988 for the MDIO functions) For OF PHY to be correctly autoprobed, the MDIO driver needs to attached to the MDIO node (the parent of the PHY nodes) With such change the MDIO driver can be binded with the MDIO node instead of the switch node as previously required. Link: https://lore.kernel.org/r/[email protected]
2026-02-23net: mdio-mt7531-mmio: improve parsing of switch register on probeChristian Marangi
The MDIO node is ALWAYS a parent of the MT7531 switch node and the MDIO registers are in the MT7531 register space (in the context of MT7988 it's all memory-mapped) With these assumption, we can simplify and permit better usage of PHY OF automatic probing by binding the mt7531-mdio-mmio driver with the MDIO node instead of the switch node. For OF PHY to be correctly autoprobed, the MDIO driver needs to attached to the MDIO node (the parent of the PHY nodes). The driver will reach the parent node (the switch node) and will parse the register address from there. Signed-off-by: Christian Marangi <[email protected]>
2026-02-23net: mdio-mt7531-mmio: use common header priv structChristian Marangi
Instead of having duplicate priv struct for mdio-mt7531-mmio driver in both driver and header, use the one exposed by the header directly. This make sure we have consistent priv struct if the driver will be updated in the future. Signed-off-by: Christian Marangi <[email protected]>
2026-02-23Merge patch series "am62dxx-evm: Add SPI flash support"Tom Rini
Paresh Bhagat <[email protected]> says: This series enables SPI flash support for the AM62DX EVM platform. The first patch enables the required SPI flash configuration options in both A53 and R5 defconfigs, including Cadence QSPI driver support, SFDP support, and Spansion S28HX-T flash compatibility. The second patch adds the necessary device tree configuration for the R5 SPL to support OSPI flash access during the boot process. Boot logs https://gist.github.com/paresh-bhagat12/ca9a05aa443c71e8baf6d8506f6ccc22 Link: https://lore.kernel.org/r/[email protected]
2026-02-23configs: am62dx_evm: Enable SPI flash supportParesh Bhagat
Enable SPI flash support for AM62DX EVM by adding Cadence QSPI driver, configuring 25MHz speed, and enabling SFDP support with Spansion S28HX-T flash compatibility. Enable required SPI and MTD configs for both A53 and R5 configurations to allow booting from SPI flash. Signed-off-by: Paresh Bhagat <[email protected]>
2026-02-23arm: dts: k3-am62d2-r5: Add DMA and OSPI configurationParesh Bhagat
Enable WKUP UART0 for DM firmware logs, configure DMA controllers with TI SCI references, and update OSPI0 register mapping. Signed-off-by: Paresh Bhagat <[email protected]>
2026-02-23Merge tag 'v2026.04-rc3' into nextTom Rini
Prepare v2026.04-rc3
2026-02-23Prepare v2026.04-rc3v2026.04-rc3Tom Rini
Signed-off-by: Tom Rini <[email protected]>
2026-02-23fs/squashfs: fix heap buffer overflow in sqfs_frag_lookup()Eric Kilmer
sqfs_frag_lookup() reads a 16-bit metadata block header whose lower 15 bits encode the data size. Unlike sqfs_read_metablock() in sqfs_inode.c, this function does not validate that the decoded size is within SQFS_METADATA_BLOCK_SIZE (8192). A malformed SquashFS image can set the size field to any value up to 32767, causing memcpy to write past the 8192-byte 'entries' heap buffer. Add the same bounds check used by sqfs_read_metablock(): reject any metadata block header with SQFS_METADATA_SIZE(header) exceeding SQFS_METADATA_BLOCK_SIZE. Found by fuzzing with libFuzzer + AddressSanitizer. Signed-off-by: Eric Kilmer <[email protected]> Reviewed-by: Miquel Raynal <[email protected]>
2026-02-23doc: board: samsung: exynos-mobile: remove requirement of stub device treeKaustabh Chakraborty
Flashing U-Boot for Exynos 7870 requires creating a stub device tree, where certain properties and nodes are defined which are populated by the previous bootloader in the phones. Since these properties are now available in the U-Boot device tree, it's now possible to use the same blob generated by U-Boot in place of the stub, when creating boot images. Update the build documentation to reflect the same. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-23ARM: dts: exynos7870-on7xelte: add properties to make S-BOOT happyKaustabh Chakraborty
Add properties in the DTSI file which is required for S-BOOT when used an external device tree when booting into U-Boot. S-BOOT is Samsung's proprietary bootloader, which chainloads U-Boot. Since this device has multiple bank nodes, add memory nodes for each RAM bank. This is the format S-BOOT recognizes, and (re)populates it with the correct bank sizes. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-23ARM: dts: exynos7870-j6lte: add properties to make S-BOOT happyKaustabh Chakraborty
Add properties in the DTSI file which is required for S-BOOT when used an external device tree when booting into U-Boot. S-BOOT is Samsung's proprietary bootloader, which chainloads U-Boot. Since this device has multiple bank nodes, add memory nodes for each RAM bank. This is the format S-BOOT recognizes, and (re)populates it with the correct bank sizes. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-23ARM: dts: exynos7870-a2corelte: add properties to make S-BOOT happyKaustabh Chakraborty
Add properties in the DTSI file which is required for S-BOOT when used an external device tree when booting into U-Boot. S-BOOT is Samsung's proprietary bootloader, which chainloads U-Boot. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-23doc: board: samsung: exynos-mobile: use u-boot-nodtb.bin for packaging processKaustabh Chakraborty
U-Boot for this board is programmed to use the external DTB if an internal device tree is not available. This makes it safe to build boot images using the non-DTB U-Boot binary, while taking up less space. Reflect this change in documentation. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-23doc: board: samsung: exynos-mobile: add DEVICE_TREE make flag in buildKaustabh Chakraborty
Since there is only one internal device tree allowed in U-Boot, the DEVICE_TREE flag is required for building images for various devices. Document it in the build guide. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>
2026-02-23configs: exynos-mobile: remove DEFAULT_DEVICE_TREE and add ↵Kaustabh Chakraborty
OF_UPSTREAM_BUILD_VENDOR Since the build documentation recommends using the DEVICE_TREE= make flag, and the "board" supports multiple devices, remove the default device tree option so as to enforce the make flag during build. OF_UPSTREAM_BUILD_VENDOR is added so as to build all device trees associated with the vendor with their U-Boot includes. Signed-off-by: Kaustabh Chakraborty <[email protected]> Signed-off-by: Minkyu Kang <[email protected]>