all: dtbs
 endif
 
+ifdef CONFIG_GENERIC_BUILTIN_DTB
+vmlinux: dtbs
+endif
+
 endif
 
 PHONY += scripts_dtc
               modules.builtin modules.builtin.modinfo modules.nsdeps \
               modules.builtin.ranges vmlinux.o.map \
               compile_commands.json rust/test \
-              rust-project.json .vmlinux.objs .vmlinux.export.c
+              rust-project.json .vmlinux.objs .vmlinux.export.c \
+               .builtin-dtbs-list .builtin-dtb.S
 
 # Directories & files removed with 'make mrproper'
 MRPROPER_FILES += include/config include/generated          \
 
 %.o: %.c FORCE
        $(call if_changed_dep,cc_o_c)
 
+quiet_cmd_as_o_S = AS      $@
+      cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $<
+
+%.o: %.S FORCE
+       $(call if_changed_dep,as_o_S)
+
+# Built-in dtb
+# ---------------------------------------------------------------------------
+
+quiet_cmd_wrap_dtbs = WRAP    $@
+      cmd_wrap_dtbs = {                                                        \
+       echo '\#include <asm-generic/vmlinux.lds.h>';                   \
+       echo '.section .dtb.init.rodata,"a"';                           \
+       while read dtb; do                                              \
+               symbase=__dtb_$$(basename -s .dtb "$${dtb}" | tr - _);  \
+               echo '.balign STRUCT_ALIGNMENT';                        \
+               echo ".global $${symbase}_begin";                       \
+               echo "$${symbase}_begin:";                              \
+               echo '.incbin "'$$dtb'" ';                              \
+               echo ".global $${symbase}_end";                         \
+               echo "$${symbase}_end:";                                \
+       done < $<;                                                      \
+       } > $@
+
+.builtin-dtbs.S: .builtin-dtbs-list FORCE
+       $(call if_changed,wrap_dtbs)
+
+quiet_cmd_gen_dtbs_list = GEN     $@
+      cmd_gen_dtbs_list = \
+       $(if $(CONFIG_BUILTIN_DTB_NAME), echo "arch/$(SRCARCH)/boot/dts/$(CONFIG_BUILTIN_DTB_NAME).dtb",:) > $@
+
+.builtin-dtbs-list: arch/$(SRCARCH)/boot/dts/dtbs-list FORCE
+       $(call if_changed,$(if $(CONFIG_BUILTIN_DTB_ALL),copy,gen_dtbs_list))
+
+targets += .builtin-dtbs-list
+
+ifdef CONFIG_GENERIC_BUILTIN_DTB
+targets += .builtin-dtbs.S .builtin-dtbs.o
+vmlinux: .builtin-dtbs.o
+endif
+
+# vmlinux
+# ---------------------------------------------------------------------------
+
 ifdef CONFIG_MODULES
 targets += .vmlinux.export.o
 vmlinux: .vmlinux.export.o