Skip to content

Instantly share code, notes, and snippets.

@mcgrof
Created September 15, 2021 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcgrof/93d7389f22f07432a2ba8d7c1514c5b8 to your computer and use it in GitHub Desktop.
Save mcgrof/93d7389f22f07432a2ba8d7c1514c5b8 to your computer and use it in GitHub Desktop.
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index ab45a220fac4..d6bfdfb0f0af 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -130,14 +130,11 @@ static inline unsigned int x86_cpuid_family(void)
extern void __init load_ucode_bsp(void);
extern void load_ucode_ap(void);
void reload_early_microcode(void);
-extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
extern bool initrd_gone;
#else
static inline void __init load_ucode_bsp(void) { }
static inline void load_ucode_ap(void) { }
static inline void reload_early_microcode(void) { }
-static inline bool
-get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; }
#endif
#endif /* _ASM_X86_MICROCODE_H */
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 3d4a48336084..ae2a179a44da 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -456,17 +456,25 @@ apply_microcode_early_amd(u32 cpuid_1_eax, void *ucode, size_t size, bool save_p
static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
{
-#ifdef CONFIG_X86_64
char fw_name[36] = "amd-ucode/microcode_amd.bin";
+ const struct firmware fw;
+ int ret;
+
+ if (IS_ENABLED(CONFIG_X86_32))
+ return false;
if (family >= 0x15)
snprintf(fw_name, sizeof(fw_name),
"amd-ucode/microcode_amd_fam%.2xh.bin", family);
- return get_builtin_firmware(cp, fw_name);
-#else
+ ret = firmware_request_builtin(&fw, fw_name);
+ if (ret == 0) {
+ cp->size = fw.size;
+ cp->data = (void *)fw.data;
+ return true;
+ }
+
return false;
-#endif
}
static void __load_ucode_amd(unsigned int cpuid_1_eax, struct cpio_data *ret)
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 7e8e07bddd5f..6752053d3ae3 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -457,6 +457,8 @@ static bool load_builtin_intel_microcode(struct cpio_data *cp)
{
unsigned int eax = 1, ebx, ecx = 0, edx;
char name[30];
+ const struct firmware fw;
+ int ret;
if (IS_ENABLED(CONFIG_X86_32))
return false;
@@ -466,7 +468,13 @@ static bool load_builtin_intel_microcode(struct cpio_data *cp)
sprintf(name, "intel-ucode/%02x-%02x-%02x",
x86_family(eax), x86_model(eax), x86_stepping(eax));
- return get_builtin_firmware(cp, name);
+ ret = firmware_request_builtin(&fw, name);
+ if (ret == 0) {
+ cp->size = fw.size;
+ cp->data = (void *)fw.data;
+ }
+
+ return false;
}
/*
diff --git a/drivers/base/firmware_loader/firmware.h b/drivers/base/firmware_loader/firmware.h
index a3014e9e2c85..7865dea190d5 100644
--- a/drivers/base/firmware_loader/firmware.h
+++ b/drivers/base/firmware_loader/firmware.h
@@ -34,6 +34,11 @@
* fallback are enabled, then this fallback will be tried first.
* @FW_OPT_PARTIAL: Allow partial read of firmware instead of needing to read
* entire file.
+ * @FW_OPT_NO_ALLOC_BUILTIN: The caller has a requirement so that the memory
+ * allocator is not used, as such the firmware pointer passed is allocated
+ * as part of the stack on the caller side and the type of firmware it is
+ * looking for must only be built-in. Because of this it does not need to
+ * use the release_firmware() call.
*/
enum fw_opt {
FW_OPT_UEVENT = BIT(0),
@@ -44,6 +49,7 @@ enum fw_opt {
FW_OPT_NOFALLBACK_SYSFS = BIT(5),
FW_OPT_FALLBACK_PLATFORM = BIT(6),
FW_OPT_PARTIAL = BIT(7),
+ FW_OPT_NO_ALLOC_BUILTIN = BIT(8),
};
enum fw_status {
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index bdbedc6660a8..ce629bd20941 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -729,11 +729,13 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
struct fw_priv *fw_priv;
int ret;
- *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
- if (!firmware) {
- dev_err(device, "%s: kmalloc(struct firmware) failed\n",
- __func__);
- return -ENOMEM;
+ if (!(opt_flags & FW_OPT_NO_ALLOC_BUILTIN)) {
+ *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
+ if (!firmware) {
+ dev_err(device, "%s: kmalloc(struct firmware) failed\n",
+ __func__);
+ return -ENOMEM;
+ }
}
if (fw_get_builtin_firmware(firmware, name, dbuf, size)) {
@@ -741,6 +743,9 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
return 0; /* assigned */
}
+ if (opt_flags & FW_OPT_NO_ALLOC_BUILTIN)
+ return -ENOENT;
+
ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv, dbuf, size,
offset, opt_flags);
@@ -805,6 +810,9 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
goto out;
}
+ if (opt_flags & FW_OPT_NO_ALLOC_BUILTIN)
+ fw = *firmware_p;
+
ret = _request_firmware_prepare(&fw, name, device, buf, size,
offset, opt_flags);
if (ret <= 0) /* error or already assigned */
@@ -933,6 +941,20 @@ int request_firmware_direct(const struct firmware **firmware_p,
}
EXPORT_SYMBOL_GPL(request_firmware_direct);
+int firmware_request_builtin(const struct firmware *firmware, const char *name)
+{
+ int ret;
+
+ __module_get(THIS_MODULE);
+ ret = _request_firmware(&firmware, name, NULL, NULL, 0, 0,
+ FW_OPT_UEVENT | FW_OPT_NO_WARN |
+ FW_OPT_NOFALLBACK_SYSFS |
+ FW_OPT_NO_ALLOC_BUILTIN);
+ module_put(THIS_MODULE);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(firmware_request_builtin);
+
/**
* firmware_request_platform() - request firmware with platform-fw fallback
* @firmware: pointer to firmware image
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index 25109192cebe..29716e822500 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -51,6 +51,7 @@ int request_firmware_nowait(
void (*cont)(const struct firmware *fw, void *context));
int request_firmware_direct(const struct firmware **fw, const char *name,
struct device *device);
+int firmware_request_builtin(const struct firmware *firmware, const char *name);
int request_firmware_into_buf(const struct firmware **firmware_p,
const char *name, struct device *device, void *buf, size_t size);
int request_partial_firmware_into_buf(const struct firmware **firmware_p,
@@ -99,6 +100,12 @@ static inline int request_firmware_direct(const struct firmware **fw,
return -EINVAL;
}
+static inline int firmware_request_builtin(const struct firmware *firmware,
+ const char *name)
+{
+ return -EINVAL;
+}
+
static inline int request_firmware_into_buf(const struct firmware **firmware_p,
const char *name, struct device *device, void *buf, size_t size)
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment