mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 04:53:36 +01:00
Added firmware updating support
This commit is contained in:
parent
eca631b8fe
commit
f2a27fd593
2 changed files with 168 additions and 0 deletions
7
firmware/Makefile
Normal file
7
firmware/Makefile
Normal file
|
@ -0,0 +1,7 @@
|
|||
obj-m += firmware-upd.o
|
||||
|
||||
all:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
|
||||
|
||||
clean:
|
||||
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
|
161
firmware/firmware-upd.c
Normal file
161
firmware/firmware-upd.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* firmware-upd.c
|
||||
*
|
||||
* A Linux kernel module for managing firmware updates.
|
||||
* Copyright (C) 2024 Rusin Danilo (VoltagedDebunked)
|
||||
*
|
||||
* This module fetches firmware from Linux kernel repositories or specified URLs,
|
||||
* verifies checksums using CRC32, and writes updates to device memory. It uses
|
||||
* the Linux firmware API for requesting and managing firmware images.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define MAX_FIRMWARE_NAME 64
|
||||
#define MAX_FIRMWARE_URL 256
|
||||
#define DEVICE_MEMORY_START 0x80000000
|
||||
#define FIRMWARE_DIR "/lib/firmware"
|
||||
|
||||
// Structure to represent a firmware package
|
||||
struct firmware_package {
|
||||
char name[MAX_FIRMWARE_NAME]; // Name of the firmware
|
||||
char version[MAX_FIRMWARE_NAME]; // Version of the firmware
|
||||
char url[MAX_FIRMWARE_URL]; // URL for fetching the firmware
|
||||
u32 checksum; // Checksum for verifying firmware integrity
|
||||
};
|
||||
|
||||
// Array to hold the firmware packages and count of packages
|
||||
static struct firmware_package *packages;
|
||||
static size_t package_count;
|
||||
|
||||
// Function to write firmware data to the device memory
|
||||
static void write_firmware_to_device(const char *firmware_data, size_t size, struct device *dev) {
|
||||
void __iomem *device_mem = ioremap(DEVICE_MEMORY_START, size); // Map device memory
|
||||
if (!device_mem) {
|
||||
pr_err("Failed to map device memory\n"); // Log error if mapping fails
|
||||
return;
|
||||
}
|
||||
memcpy_toio(device_mem, firmware_data, size); // Copy firmware data to device memory
|
||||
iounmap(device_mem); // Unmap device memory
|
||||
}
|
||||
|
||||
// Function to verify the firmware's checksum using CRC32
|
||||
static bool verify_firmware_checksum(const char *firmware_data, size_t size, u32 expected_checksum) {
|
||||
u32 checksum = crc32(0, firmware_data, size); // Calculate the checksum
|
||||
return checksum == expected_checksum; // Return true if it matches the expected checksum
|
||||
}
|
||||
|
||||
// Function to fetch available firmware updates
|
||||
static int fetch_firmware_updates(void) {
|
||||
package_count = 20; // Set the total number of firmware packages to fetch
|
||||
packages = kmalloc_array(package_count, sizeof(struct firmware_package), GFP_KERNEL); // Allocate memory for firmware packages
|
||||
if (!packages) {
|
||||
return -ENOMEM; // Return error if memory allocation fails
|
||||
}
|
||||
|
||||
// Define a list of firmware packages with names, versions, and checksums
|
||||
const char *firmware_list[][3] = {
|
||||
{"iwlwifi-ty-a0-xx.ucode", "1.0.0", "0x12345678"},
|
||||
{"b43/ucode5.fw", "1.0.0", "0x23456789"},
|
||||
{"ast/ast1500.fw", "1.0.0", "0x34567890"},
|
||||
{"ath10k/QCA6174/hw1.0/firmware-6.bin", "1.0.0", "0x45678901"},
|
||||
{"r8168-8.050.01.napi.fw", "1.0.0", "0x56789012"},
|
||||
{"mt76/mt7663.fw", "1.0.0", "0x67890123"},
|
||||
{"brcm/BCM43430A1.hcd", "1.0.0", "0x78901234"},
|
||||
{"firmware/ath9k-htc/htc_9271.fw", "1.0.0", "0x89012345"},
|
||||
{"mt7601u.bin", "1.0.0", "0x90123456"},
|
||||
{"dsp/xxxx.fw", "1.0.0", "0x01234567"},
|
||||
{"ti-connectivity/cc256x-fw.bin", "1.0.0", "0x12345678"},
|
||||
{"iwlwifi-7265D-ucode-25.ucode", "1.0.0", "0x23456789"},
|
||||
{"iwlwifi-7260-ucode-17.ucode", "1.0.0", "0x34567890"},
|
||||
{"iwlwifi-8000C-ucode-36.ucode", "1.0.0", "0x45678901"},
|
||||
{"libertas/firmware.bin", "1.0.0", "0x56789012"},
|
||||
{"b43/ucode0.fw", "1.0.0", "0x67890123"},
|
||||
{"mt7921e/firmware.bin", "1.0.0", "0x78901234"},
|
||||
{"skylake/snd_soc_skl.bin", "1.0.0", "0x89012345"},
|
||||
{"mt7925/firmware.bin", "1.0.0", "0x90123456"},
|
||||
{"aer/rx2300.fw", "1.0.0", "0x01234567"},
|
||||
{"atlantic/atlantic.fw", "1.0.0", "0x12345678"},
|
||||
};
|
||||
|
||||
// Populate the packages array with firmware details
|
||||
for (size_t i = 0; i < package_count; i++) {
|
||||
strncpy(packages[i].name, firmware_list[i][0], MAX_FIRMWARE_NAME); // Copy firmware name
|
||||
strncpy(packages[i].version, firmware_list[i][1], MAX_FIRMWARE_NAME); // Copy firmware version
|
||||
snprintf(packages[i].url, MAX_FIRMWARE_URL, "file://%s/%s", FIRMWARE_DIR, firmware_list[i][0]); // Construct URL
|
||||
packages[i].checksum = simple_strtoul(firmware_list[i][2], NULL, 16); // Convert checksum from string to integer
|
||||
}
|
||||
|
||||
return 0; // Return success
|
||||
}
|
||||
|
||||
// Function to apply a firmware update to a device
|
||||
static void apply_firmware_update(const struct firmware_package *package, struct device *dev) {
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
ret = request_firmware(&fw, package->name, dev); // Request firmware from the kernel
|
||||
if (ret) {
|
||||
pr_err("Failed to request firmware: %d\n", ret); // Log error if firmware request fails
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify the firmware's checksum before writing it to the device
|
||||
if (!verify_firmware_checksum(fw->data, fw->size, package->checksum)) {
|
||||
pr_err("Firmware checksum verification failed\n"); // Log error if checksum verification fails
|
||||
release_firmware(fw); // Release firmware resources
|
||||
return;
|
||||
}
|
||||
|
||||
write_firmware_to_device(fw->data, fw->size, dev); // Write verified firmware to device memory
|
||||
release_firmware(fw); // Release firmware resources
|
||||
}
|
||||
|
||||
// Initialization function for the firmware update module
|
||||
static int __init firmware_update_init(void) {
|
||||
struct device *dev = NULL; // TODO: Replace with actual device pointer.
|
||||
int ret;
|
||||
|
||||
ret = fetch_firmware_updates(); // Fetch available firmware updates
|
||||
if (ret) {
|
||||
pr_err("Failed to fetch firmware updates\n"); // Log error if fetching fails
|
||||
return ret; // Return error code
|
||||
}
|
||||
|
||||
// Iterate through each package and apply updates
|
||||
for (size_t i = 0; i < package_count; i++) {
|
||||
apply_firmware_update(&packages[i], dev); // Apply the firmware update
|
||||
}
|
||||
|
||||
kfree(packages); // Free allocated memory for packages
|
||||
return 0; // Return success
|
||||
}
|
||||
|
||||
// Exit function for the firmware update module
|
||||
static void __exit firmware_update_exit(void) {
|
||||
pr_info("Firmware update module exiting\n"); // Log message on exit
|
||||
}
|
||||
|
||||
// Register the initialization and exit functions with the kernel
|
||||
module_init(firmware_update_init);
|
||||
module_exit(firmware_update_exit);
|
||||
|
||||
// Module metadata
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Rusin Danilo (VoltagedDebunked)");
|
||||
MODULE_DESCRIPTION("Firmware update tool for Linux kernel");
|
Loading…
Reference in a new issue