firmware: Add firmware installation to modules_install, add firmware_install

For 'make modules_install', install any firmware required by
the modules which are being installed.

Also add a 'make firmware_install' target which doesn't depend on the
configuration, but installs _all_ available in-kernel-tree firmware into
$(INSTALL_FW_PATH), which defaults to /lib/firmware. This is intended
for distributors to make arch-independent (and config-independent)
packages containing firmware.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
diff --git a/Makefile b/Makefile
index f398cff..bd2aa14 100644
--- a/Makefile
+++ b/Makefile
@@ -995,6 +995,16 @@
 	@echo '*** Warning: make $@ is unnecessary now.'
 
 # ---------------------------------------------------------------------------
+# Firmware install
+INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware
+export INSTALL_FW_PATH
+
+PHONY += firmware_install
+firmware_install: FORCE
+	@mkdir -p $(objtree)/firmware
+	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install
+
+# ---------------------------------------------------------------------------
 # Kernel headers
 INSTALL_HDR_PATH=$(objtree)/usr
 export INSTALL_HDR_PATH
@@ -1080,6 +1090,7 @@
 # boot script depmod is the master version.
 PHONY += _modinst_post
 _modinst_post: _modinst_
+	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
 	$(call cmd,depmod)
 
 else # CONFIG_MODULES
@@ -1197,6 +1208,8 @@
 	@echo  '* vmlinux	  - Build the bare kernel'
 	@echo  '* modules	  - Build all modules'
 	@echo  '  modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
+	@echo  '  firmware_install- Install all firmware to INSTALL_FW_PATH'
+	@echo  '                    (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
 	@echo  '  dir/            - Build all files in dir and below'
 	@echo  '  dir/file.[ois]  - Build specified target only'
 	@echo  '  dir/file.ko     - Build module including final link'
diff --git a/firmware/Makefile b/firmware/Makefile
index cc25f56..3742fee 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -9,13 +9,22 @@
 
 fw-external-y := $(subst ",,$(CONFIG_EXTRA_FIRMWARE))
 
-# If CONFIG_FIRMWARE_IN_KERNEL is not set, then don't include any firmware
-ifneq ($(CONFIG_FIRMWARE_IN_KERNEL),y)
-fw-shipped-y :=
-endif
+# There are three cases to care about:
+# 1. Building kernel with CONFIG_FIRMWARE_IN_KERNEL=y -- $(fw-shipped-y) should
+#    include the firmware files to include, according to .config
+# 2. 'make modules_install', which will install firmware for modules, and 
+#    _also_ for the in-kernel drivers when CONFIG_FIRMWARE_IN_KERNEL=n
+# 3. 'make firmware_install', which installs all firmware, unconditionally.
 
-firmware-y    := $(fw-external-y) $(fw-shipped-y)
-firmware-dirs := $(sort $(patsubst %,$(objtree)/$(obj)/%/,$(dir $(firmware-y) $(fw-shipped-))))
+# For the former two cases we want $(fw-shipped-y) and $(fw-shipped-m) to be
+# accurate. In the latter case it doesn't matter -- it'll use $(fw-shipped-all).
+# But be aware that the config file might not be included at all.
+
+
+fw-shipped-all := $(fw-shipped-y) $(fw-shipped-m) $(fw-shipped-)
+
+# Directories which we _might_ need to create, so we have a rule for them.
+firmware-dirs := $(sort $(patsubst %,$(objtree)/$(obj)/%/,$(dir $(fw-external-y) $(fw-shipped-all))))
 
 quiet_cmd_mkdir = MKDIR   $(patsubst $(objtree)/%,%,$@)
       cmd_mkdir = mkdir -p $@
@@ -81,7 +90,8 @@
 $(firmware-dirs):
 	$(call cmd,mkdir)
 
-obj-y := $(patsubst %,%.gen.o, $(firmware-y))
+obj-y				 += $(patsubst %,%.gen.o, $(fw-external-y))
+obj-$(CONFIG_FIRMWARE_IN_KERNEL) += $(patsubst %,%.gen.o, $(fw-shipped-y))
 
 # Remove .S files and binaries created from ihex
 # (during 'make clean' .config isn't included so they're all in $(fw-shipped-))
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
new file mode 100644
index 0000000..1c03008
--- /dev/null
+++ b/scripts/Makefile.fwinst
@@ -0,0 +1,45 @@
+# ==========================================================================
+# Installing firmware
+#
+# We don't include the .config, so all firmware files are in $(fw-shipped-)
+# rather than in $(fw-shipped-y) or $(fw-shipped-n).
+# ==========================================================================
+
+INSTALL := install
+
+# For modules_install installing firmware, we want to see .config
+# But for firmware_install, we don't care, but don't want to require it.
+-include $(objtree)/.config
+
+include scripts/Kbuild.include
+include $(srctree)/$(obj)/Makefile
+
+include scripts/Makefile.host
+
+mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-m))
+
+# If CONFIG_FIRMWARE_IN_KERNEL isn't set, then install the 
+# firmware for in-kernel drivers too.
+ifndef CONFIG_FIRMWARE_IN_KERNEL
+mod-fw += $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-y))
+endif
+
+installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
+installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
+
+quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
+      cmd_install = $(INSTALL) -m0644 $< $@
+
+$(installed-fw-dirs):
+	$(call cmd,mkdir)
+
+$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %)/
+	$(call cmd,install)
+
+.PHONY: __fw_install __fw_modinst FORCE
+
+__fw_install: $(installed-fw)
+__fw_modinst: $(mod-fw)
+
+
+FORCE: