Added firmware updating support

This commit is contained in:
Voltaged 2024-10-15 15:30:35 +01:00 committed by GitHub
parent eca631b8fe
commit f2a27fd593
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 168 additions and 0 deletions

7
firmware/Makefile Normal file
View 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
View 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");