cpucontrol(8): De-duplicate common update logic
Every µcode-updater must open the cpucontrol devfs node RDWR, open a firmware file, validate the FW file has a positive length, mmap it, etc. De-duplicate that identical logic between every individual platform. Also, constify references to the readonly-mapped firmware files while here. Sponsored by: Dell EMC Isilon
This commit is contained in:
parent
91cf497515
commit
dee401e833
@ -73,16 +73,16 @@ amd_probe(int fd)
|
||||
}
|
||||
|
||||
void
|
||||
amd_update(const char *dev, const char *path)
|
||||
amd_update(const struct ucode_update_params *params)
|
||||
{
|
||||
int fd, devfd;
|
||||
int devfd;
|
||||
unsigned int i;
|
||||
struct stat st;
|
||||
uint32_t *fw_image;
|
||||
amd_fw_header_t *fw_header;
|
||||
const char *dev, *path;
|
||||
const uint32_t *fw_image;
|
||||
const amd_fw_header_t *fw_header;
|
||||
uint32_t sum;
|
||||
uint32_t signature;
|
||||
uint32_t *fw_data;
|
||||
const uint32_t *fw_data;
|
||||
size_t fw_size;
|
||||
cpuctl_cpuid_args_t idargs = {
|
||||
.level = 1, /* Request signature. */
|
||||
@ -90,16 +90,14 @@ amd_update(const char *dev, const char *path)
|
||||
cpuctl_update_args_t args;
|
||||
int error;
|
||||
|
||||
dev = params->dev_path;
|
||||
path = params->fw_path;
|
||||
devfd = params->devfd;
|
||||
fw_image = params->fwimage;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
fd = -1;
|
||||
fw_image = MAP_FAILED;
|
||||
devfd = open(dev, O_RDWR);
|
||||
if (devfd < 0) {
|
||||
WARN(0, "could not open %s for writing", dev);
|
||||
return;
|
||||
}
|
||||
error = ioctl(devfd, CPUCTL_CPUID, &idargs);
|
||||
if (error < 0) {
|
||||
WARN(0, "ioctl()");
|
||||
@ -115,37 +113,18 @@ amd_update(const char *dev, const char *path)
|
||||
/*
|
||||
* Open the firmware file.
|
||||
*/
|
||||
fd = open(path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
WARN(0, "open(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
error = fstat(fd, &st);
|
||||
if (error != 0) {
|
||||
WARN(0, "fstat(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
if (st.st_size < 0 || (unsigned)st.st_size < sizeof(*fw_header)) {
|
||||
if (params->fwsize < sizeof(*fw_header)) {
|
||||
WARNX(2, "file too short: %s", path);
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* mmap the whole image.
|
||||
*/
|
||||
fw_image = (uint32_t *)mmap(NULL, st.st_size, PROT_READ,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
if (fw_image == MAP_FAILED) {
|
||||
WARN(0, "mmap(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
fw_header = (amd_fw_header_t *)fw_image;
|
||||
fw_header = (const amd_fw_header_t *)fw_image;
|
||||
if ((fw_header->magic >> 8) != AMD_MAGIC) {
|
||||
WARNX(2, "%s is not a valid amd firmware: version mismatch",
|
||||
path);
|
||||
goto fail;
|
||||
}
|
||||
fw_data = (uint32_t *)(fw_header + 1);
|
||||
fw_size = (st.st_size - sizeof(*fw_header)) / sizeof(uint32_t);
|
||||
fw_data = (const uint32_t *)(fw_header + 1);
|
||||
fw_size = (params->fwsize - sizeof(*fw_header)) / sizeof(uint32_t);
|
||||
|
||||
/*
|
||||
* Check the primary checksum.
|
||||
@ -160,8 +139,8 @@ amd_update(const char *dev, const char *path)
|
||||
if (signature == fw_header->signature) {
|
||||
fprintf(stderr, "%s: updating cpu %s... ", path, dev);
|
||||
|
||||
args.data = fw_image;
|
||||
args.size = st.st_size;
|
||||
args.data = __DECONST(void *, fw_image);
|
||||
args.size = params->fwsize;
|
||||
error = ioctl(devfd, CPUCTL_UPDATE, &args);
|
||||
if (error < 0) {
|
||||
fprintf(stderr, "failed.\n");
|
||||
@ -172,12 +151,5 @@ amd_update(const char *dev, const char *path)
|
||||
}
|
||||
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (devfd >= 0)
|
||||
close(devfd);
|
||||
if (fw_image != MAP_FAILED)
|
||||
if(munmap(fw_image, st.st_size) != 0)
|
||||
warn("munmap(%s)", path);
|
||||
return;
|
||||
}
|
||||
|
@ -88,9 +88,8 @@ amd10h_probe(int fd)
|
||||
* source code.
|
||||
*/
|
||||
void
|
||||
amd10h_update(const char *dev, const char *path)
|
||||
amd10h_update(const struct ucode_update_params *params)
|
||||
{
|
||||
struct stat st;
|
||||
cpuctl_cpuid_args_t idargs;
|
||||
cpuctl_msr_args_t msrargs;
|
||||
cpuctl_update_args_t args;
|
||||
@ -100,27 +99,27 @@ amd10h_update(const char *dev, const char *path)
|
||||
const section_header_t *section_header;
|
||||
const container_header_t *container_header;
|
||||
const uint8_t *fw_data;
|
||||
uint8_t *fw_image;
|
||||
const uint8_t *fw_image;
|
||||
const char *dev, *path;
|
||||
size_t fw_size;
|
||||
size_t selected_size;
|
||||
uint32_t revision;
|
||||
uint32_t new_rev;
|
||||
uint32_t signature;
|
||||
uint16_t equiv_id;
|
||||
int fd, devfd;
|
||||
int devfd;
|
||||
unsigned int i;
|
||||
int error;
|
||||
|
||||
dev = params->dev_path;
|
||||
path = params->fw_path;
|
||||
devfd = params->devfd;
|
||||
fw_image = params->fwimage;
|
||||
fw_size = params->fwsize;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
fd = -1;
|
||||
fw_image = MAP_FAILED;
|
||||
devfd = open(dev, O_RDWR);
|
||||
if (devfd < 0) {
|
||||
WARN(0, "could not open %s for writing", dev);
|
||||
return;
|
||||
}
|
||||
idargs.level = 1;
|
||||
error = ioctl(devfd, CPUCTL_CPUID, &idargs);
|
||||
if (error < 0) {
|
||||
@ -149,33 +148,15 @@ amd10h_update(const char *dev, const char *path)
|
||||
* Open the firmware file.
|
||||
*/
|
||||
WARNX(1, "checking %s for update.", path);
|
||||
fd = open(path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
WARN(0, "open(%s)", path);
|
||||
goto done;
|
||||
}
|
||||
error = fstat(fd, &st);
|
||||
if (error != 0) {
|
||||
WARN(0, "fstat(%s)", path);
|
||||
goto done;
|
||||
}
|
||||
if (st.st_size < 0 || (size_t)st.st_size <
|
||||
if (fw_size <
|
||||
(sizeof(*container_header) + sizeof(*section_header))) {
|
||||
WARNX(2, "file too short: %s", path);
|
||||
goto done;
|
||||
}
|
||||
fw_size = st.st_size;
|
||||
|
||||
/*
|
||||
* mmap the whole image.
|
||||
*/
|
||||
fw_image = (uint8_t *)mmap(NULL, st.st_size, PROT_READ,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
if (fw_image == MAP_FAILED) {
|
||||
WARN(0, "mmap(%s)", path);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_data = fw_image;
|
||||
container_header = (const container_header_t *)fw_data;
|
||||
if (container_header->magic != AMD_10H_MAGIC) {
|
||||
@ -306,12 +287,5 @@ amd10h_update(const char *dev, const char *path)
|
||||
WARNX(0, "revision after update %#x", new_rev);
|
||||
|
||||
done:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (devfd >= 0)
|
||||
close(devfd);
|
||||
if (fw_image != MAP_FAILED)
|
||||
if (munmap(fw_image, st.st_size) != 0)
|
||||
warn("munmap(%s)", path);
|
||||
return;
|
||||
}
|
||||
|
@ -34,18 +34,20 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <sysexits.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/cpuctl.h>
|
||||
@ -74,16 +76,6 @@ int verbosity_level = 0;
|
||||
#define HIGH(val) (uint32_t)(((val) >> 32) & 0xffffffff)
|
||||
#define LOW(val) (uint32_t)((val) & 0xffffffff)
|
||||
|
||||
/*
|
||||
* Macros for freeing SLISTs, probably must be in /sys/queue.h
|
||||
*/
|
||||
#define SLIST_FREE(head, field, freef) do { \
|
||||
typeof(SLIST_FIRST(head)) __elm0; \
|
||||
typeof(SLIST_FIRST(head)) __elm; \
|
||||
SLIST_FOREACH_SAFE(__elm, (head), field, __elm0) \
|
||||
(void)(freef)(__elm); \
|
||||
} while(0);
|
||||
|
||||
struct datadir {
|
||||
const char *path;
|
||||
SLIST_ENTRY(datadir) next;
|
||||
@ -102,7 +94,6 @@ static struct ucode_handler {
|
||||
#define NHANDLERS (sizeof(handlers) / sizeof(*handlers))
|
||||
|
||||
static void usage(void);
|
||||
static int isdir(const char *path);
|
||||
static int do_cpuid(const char *cmdarg, const char *dev);
|
||||
static int do_cpuid_count(const char *cmdarg, const char *dev);
|
||||
static int do_msr(const char *cmdarg, const char *dev);
|
||||
@ -122,20 +113,6 @@ usage(void)
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
static int
|
||||
isdir(const char *path)
|
||||
{
|
||||
int error;
|
||||
struct stat st;
|
||||
|
||||
error = stat(path, &st);
|
||||
if (error < 0) {
|
||||
WARN(0, "stat(%s)", path);
|
||||
return (error);
|
||||
}
|
||||
return (st.st_mode & S_IFDIR);
|
||||
}
|
||||
|
||||
static int
|
||||
do_cpuid(const char *cmdarg, const char *dev)
|
||||
{
|
||||
@ -360,17 +337,78 @@ do_eval_cpu_features(const char *dev)
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
try_a_fw_image(const char *dev_path, int devfd, int fwdfd, const char *dpath,
|
||||
const char *fname, struct ucode_handler *handler)
|
||||
{
|
||||
struct ucode_update_params parm;
|
||||
struct stat st;
|
||||
char *fw_path;
|
||||
void *fw_map;
|
||||
int fwfd, rc;
|
||||
|
||||
rc = 0;
|
||||
fw_path = NULL;
|
||||
fw_map = MAP_FAILED;
|
||||
fwfd = openat(fwdfd, fname, O_RDONLY);
|
||||
if (fwfd < 0) {
|
||||
WARN(0, "openat(%s, %s)", dpath, fname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = asprintf(&fw_path, "%s/%s", dpath, fname);
|
||||
if (rc == -1) {
|
||||
WARNX(0, "out of memory");
|
||||
rc = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = fstat(fwfd, &st);
|
||||
if (rc != 0) {
|
||||
WARN(0, "fstat(%s)", fw_path);
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
if (st.st_size <= 0) {
|
||||
WARN(0, "%s: empty", fw_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fw_map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fwfd, 0);
|
||||
if (fw_map == MAP_FAILED) {
|
||||
WARN(0, "mmap(%s)", fw_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
memset(&parm, 0, sizeof(parm));
|
||||
parm.devfd = devfd;
|
||||
parm.fwimage = fw_map;
|
||||
parm.fwsize = st.st_size;
|
||||
parm.dev_path = dev_path;
|
||||
parm.fw_path = fw_path;
|
||||
|
||||
handler->update(&parm);
|
||||
|
||||
out:
|
||||
if (fw_map != MAP_FAILED)
|
||||
munmap(fw_map, st.st_size);
|
||||
free(fw_path);
|
||||
if (fwfd >= 0)
|
||||
close(fwfd);
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
do_update(const char *dev)
|
||||
{
|
||||
int fd;
|
||||
int fd, fwdfd;
|
||||
unsigned int i;
|
||||
int error;
|
||||
struct ucode_handler *handler;
|
||||
struct datadir *dir;
|
||||
DIR *dirp;
|
||||
struct dirent *direntry;
|
||||
char buf[MAXPATHLEN];
|
||||
|
||||
fd = open(dev, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
@ -379,7 +417,7 @@ do_update(const char *dev)
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the appropriate handler for device.
|
||||
* Find the appropriate handler for CPU.
|
||||
*/
|
||||
for (i = 0; i < NHANDLERS; i++)
|
||||
if (handlers[i].probe(fd) == 0)
|
||||
@ -387,39 +425,54 @@ do_update(const char *dev)
|
||||
if (i < NHANDLERS)
|
||||
handler = &handlers[i];
|
||||
else {
|
||||
WARNX(0, "cannot find the appropriate handler for device");
|
||||
WARNX(0, "cannot find the appropriate handler for %s", dev);
|
||||
close(fd);
|
||||
return (1);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
fd = open(dev, O_RDWR);
|
||||
if (fd < 0) {
|
||||
WARN(0, "error opening %s for writing", dev);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process every image in specified data directories.
|
||||
*/
|
||||
SLIST_FOREACH(dir, &datadirs, next) {
|
||||
dirp = opendir(dir->path);
|
||||
if (dirp == NULL) {
|
||||
WARNX(1, "skipping directory %s: not accessible", dir->path);
|
||||
fwdfd = open(dir->path, O_RDONLY);
|
||||
if (fwdfd < 0) {
|
||||
WARN(1, "skipping directory %s: not accessible", dir->path);
|
||||
continue;
|
||||
}
|
||||
dirp = fdopendir(fwdfd);
|
||||
if (dirp == NULL) {
|
||||
WARNX(0, "out of memory");
|
||||
close(fwdfd);
|
||||
close(fd);
|
||||
return (1);
|
||||
}
|
||||
|
||||
while ((direntry = readdir(dirp)) != NULL) {
|
||||
if (direntry->d_namlen == 0)
|
||||
continue;
|
||||
error = snprintf(buf, sizeof(buf), "%s/%s", dir->path,
|
||||
direntry->d_name);
|
||||
if ((unsigned)error >= sizeof(buf))
|
||||
WARNX(0, "skipping %s, buffer too short",
|
||||
direntry->d_name);
|
||||
if (isdir(buf) != 0) {
|
||||
WARNX(2, "skipping %s: is a directory", buf);
|
||||
if (direntry->d_type == DT_DIR)
|
||||
continue;
|
||||
|
||||
error = try_a_fw_image(dev, fd, fwdfd, dir->path,
|
||||
direntry->d_name, handler);
|
||||
if (error != 0) {
|
||||
closedir(dirp);
|
||||
close(fd);
|
||||
return (1);
|
||||
}
|
||||
handler->update(dev, buf);
|
||||
}
|
||||
error = closedir(dirp);
|
||||
if (error != 0)
|
||||
WARN(0, "closedir(%s)", dir->path);
|
||||
}
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -441,6 +494,7 @@ datadir_add(const char *path)
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct datadir *elm;
|
||||
int c, flags;
|
||||
const char *cmdarg;
|
||||
const char *dev;
|
||||
@ -511,6 +565,9 @@ main(int argc, char *argv[])
|
||||
default:
|
||||
usage(); /* Only one command can be selected. */
|
||||
}
|
||||
SLIST_FREE(&datadirs, next, free);
|
||||
while ((elm = SLIST_FIRST(&datadirs)) != NULL) {
|
||||
SLIST_REMOVE_HEAD(&datadirs, next);
|
||||
free(elm);
|
||||
}
|
||||
return (error == 0 ? 0 : 1);
|
||||
}
|
||||
|
@ -30,8 +30,17 @@
|
||||
#ifndef CPUCONTROL_H
|
||||
#define CPUCONTROL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef int ucode_probe_t(int fd);
|
||||
typedef void ucode_update_t(const char *dev, const char *image);
|
||||
struct ucode_update_params {
|
||||
int devfd; /* RDWR handle to cpucontrol device */
|
||||
const void *fwimage; /* READ mapping of firmware image */
|
||||
size_t fwsize; /* Non-zero size of firmware image */
|
||||
const char *dev_path; /* cpucontrol device path, for logging */
|
||||
const char *fw_path; /* firmware image path, for logging */
|
||||
};
|
||||
typedef void ucode_update_t(const struct ucode_update_params *params);
|
||||
|
||||
extern int verbosity_level;
|
||||
|
||||
|
@ -76,23 +76,23 @@ intel_probe(int fd)
|
||||
}
|
||||
|
||||
void
|
||||
intel_update(const char *dev, const char *path)
|
||||
intel_update(const struct ucode_update_params *params)
|
||||
{
|
||||
int fd, devfd;
|
||||
struct stat st;
|
||||
uint32_t *fw_image;
|
||||
int devfd;
|
||||
const char *dev, *path;
|
||||
const uint32_t *fw_image;
|
||||
int have_ext_table;
|
||||
uint32_t sum;
|
||||
unsigned int i;
|
||||
size_t payload_size;
|
||||
intel_fw_header_t *fw_header;
|
||||
intel_cpu_signature_t *ext_table;
|
||||
intel_ext_header_t *ext_header;
|
||||
const intel_fw_header_t *fw_header;
|
||||
const intel_cpu_signature_t *ext_table;
|
||||
const intel_ext_header_t *ext_header;
|
||||
uint32_t sig, signature, flags;
|
||||
int32_t revision;
|
||||
ssize_t ext_size;
|
||||
size_t ext_table_size;
|
||||
void *fw_data;
|
||||
const void *fw_data;
|
||||
size_t data_size, total_size;
|
||||
cpuctl_msr_args_t msrargs = {
|
||||
.msr = MSR_BIOS_SIGN,
|
||||
@ -104,18 +104,17 @@ intel_update(const char *dev, const char *path)
|
||||
cpuctl_update_args_t args;
|
||||
int error;
|
||||
|
||||
dev = params->dev_path;
|
||||
path = params->fw_path;
|
||||
devfd = params->devfd;
|
||||
fw_image = params->fwimage;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
fd = -1;
|
||||
fw_image = MAP_FAILED;
|
||||
ext_table = NULL;
|
||||
ext_header = NULL;
|
||||
devfd = open(dev, O_RDWR);
|
||||
if (devfd < 0) {
|
||||
WARN(0, "could not open %s for writing", dev);
|
||||
return;
|
||||
}
|
||||
|
||||
error = ioctl(devfd, CPUCTL_WRMSR, &msrargs);
|
||||
if (error < 0) {
|
||||
WARN(0, "ioctl(%s)", dev);
|
||||
@ -151,31 +150,12 @@ intel_update(const char *dev, const char *path)
|
||||
/*
|
||||
* Open firmware image.
|
||||
*/
|
||||
fd = open(path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
WARN(0, "open(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
error = fstat(fd, &st);
|
||||
if (error != 0) {
|
||||
WARN(0, "fstat(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
if (st.st_size < 0 || (unsigned)st.st_size < sizeof(*fw_header)) {
|
||||
if (params->fwsize < sizeof(*fw_header)) {
|
||||
WARNX(2, "file too short: %s", path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* mmap the whole image.
|
||||
*/
|
||||
fw_image = (uint32_t *)mmap(NULL, st.st_size, PROT_READ,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
if (fw_image == MAP_FAILED) {
|
||||
WARN(0, "mmap(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
fw_header = (intel_fw_header_t *)fw_image;
|
||||
fw_header = (const intel_fw_header_t *)fw_image;
|
||||
if (fw_header->header_version != INTEL_HEADER_VERSION ||
|
||||
fw_header->loader_revision != INTEL_LOADER_REVISION) {
|
||||
WARNX(2, "%s is not a valid intel firmware: version mismatch",
|
||||
@ -193,7 +173,7 @@ intel_update(const char *dev, const char *path)
|
||||
total_size = data_size + sizeof(*fw_header);
|
||||
else
|
||||
total_size = fw_header->total_size;
|
||||
if (total_size > (unsigned)st.st_size || st.st_size < 0) {
|
||||
if (total_size > params->fwsize) {
|
||||
WARNX(2, "file too short: %s", path);
|
||||
goto fail;
|
||||
}
|
||||
@ -204,7 +184,7 @@ intel_update(const char *dev, const char *path)
|
||||
*/
|
||||
sum = 0;
|
||||
for (i = 0; i < (payload_size / sizeof(uint32_t)); i++)
|
||||
sum += *((uint32_t *)fw_image + i);
|
||||
sum += *((const uint32_t *)fw_image + i);
|
||||
if (sum != 0) {
|
||||
WARNX(2, "%s: update data checksum invalid", path);
|
||||
goto fail;
|
||||
@ -217,9 +197,9 @@ intel_update(const char *dev, const char *path)
|
||||
have_ext_table = 0;
|
||||
|
||||
if (ext_size > (signed)sizeof(*ext_header)) {
|
||||
ext_header =
|
||||
(intel_ext_header_t *)((char *)fw_image + payload_size);
|
||||
ext_table = (intel_cpu_signature_t *)(ext_header + 1);
|
||||
ext_header = (const intel_ext_header_t *)
|
||||
((const char *)fw_image + payload_size);
|
||||
ext_table = (const intel_cpu_signature_t *)(ext_header + 1);
|
||||
|
||||
/*
|
||||
* Check the extended table size.
|
||||
@ -236,7 +216,7 @@ intel_update(const char *dev, const char *path)
|
||||
*/
|
||||
sum = 0;
|
||||
for (i = 0; i < (ext_table_size / sizeof(uint32_t)); i++)
|
||||
sum += *((uint32_t *)ext_header + i);
|
||||
sum += *((const uint32_t *)ext_header + i);
|
||||
if (sum != 0) {
|
||||
WARNX(2,
|
||||
"%s: extended signature table checksum invalid",
|
||||
@ -273,7 +253,7 @@ intel_update(const char *dev, const char *path)
|
||||
}
|
||||
fprintf(stderr, "%s: updating cpu %s from rev %#x to rev %#x... ",
|
||||
path, dev, revision, fw_header->revision);
|
||||
args.data = fw_data;
|
||||
args.data = __DECONST(void *, fw_data);
|
||||
args.size = data_size;
|
||||
error = ioctl(devfd, CPUCTL_UPDATE, &args);
|
||||
if (error < 0) {
|
||||
@ -286,11 +266,5 @@ intel_update(const char *dev, const char *path)
|
||||
fprintf(stderr, "done.\n");
|
||||
|
||||
fail:
|
||||
if (fw_image != MAP_FAILED)
|
||||
if (munmap(fw_image, st.st_size) != 0)
|
||||
warn("munmap(%s)", path);
|
||||
if (devfd >= 0)
|
||||
close(devfd);
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
@ -76,18 +76,18 @@ via_probe(int fd)
|
||||
}
|
||||
|
||||
void
|
||||
via_update(const char *dev, const char *path)
|
||||
via_update(const struct ucode_update_params *params)
|
||||
{
|
||||
int fd, devfd;
|
||||
struct stat st;
|
||||
uint32_t *fw_image;
|
||||
int devfd;
|
||||
const char *dev, *path;
|
||||
const uint32_t *fw_image;
|
||||
uint32_t sum;
|
||||
unsigned int i;
|
||||
size_t payload_size;
|
||||
via_fw_header_t *fw_header;
|
||||
const via_fw_header_t *fw_header;
|
||||
uint32_t signature;
|
||||
int32_t revision;
|
||||
void *fw_data;
|
||||
const void *fw_data;
|
||||
size_t data_size, total_size;
|
||||
cpuctl_msr_args_t msrargs = {
|
||||
.msr = MSR_IA32_PLATFORM_ID,
|
||||
@ -98,17 +98,14 @@ via_update(const char *dev, const char *path)
|
||||
cpuctl_update_args_t args;
|
||||
int error;
|
||||
|
||||
dev = params->dev_path;
|
||||
path = params->fw_path;
|
||||
devfd = params->devfd;
|
||||
fw_image = params->fwimage;
|
||||
|
||||
assert(path);
|
||||
assert(dev);
|
||||
|
||||
fd = -1;
|
||||
devfd = -1;
|
||||
fw_image = MAP_FAILED;
|
||||
devfd = open(dev, O_RDWR);
|
||||
if (devfd < 0) {
|
||||
WARN(0, "could not open %s for writing", dev);
|
||||
return;
|
||||
}
|
||||
error = ioctl(devfd, CPUCTL_CPUID, &idargs);
|
||||
if (error < 0) {
|
||||
WARN(0, "ioctl(%s)", dev);
|
||||
@ -134,34 +131,13 @@ via_update(const char *dev, const char *path)
|
||||
WARNX(2, "found cpu type %#x family %#x model %#x stepping %#x.",
|
||||
(signature >> 12) & 0x03, (signature >> 8) & 0x0f,
|
||||
(signature >> 4) & 0x0f, (signature >> 0) & 0x0f);
|
||||
/*
|
||||
* Open firmware image.
|
||||
*/
|
||||
fd = open(path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
WARN(0, "open(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
error = fstat(fd, &st);
|
||||
if (error != 0) {
|
||||
WARN(0, "fstat(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
if (st.st_size < 0 || (unsigned)st.st_size < sizeof(*fw_header)) {
|
||||
|
||||
if (params->fwsize < sizeof(*fw_header)) {
|
||||
WARNX(2, "file too short: %s", path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* mmap the whole image.
|
||||
*/
|
||||
fw_image = (uint32_t *)mmap(NULL, st.st_size, PROT_READ,
|
||||
MAP_PRIVATE, fd, 0);
|
||||
if (fw_image == MAP_FAILED) {
|
||||
WARN(0, "mmap(%s)", path);
|
||||
goto fail;
|
||||
}
|
||||
fw_header = (via_fw_header_t *)fw_image;
|
||||
fw_header = (const via_fw_header_t *)fw_image;
|
||||
if (fw_header->signature != VIA_HEADER_SIGNATURE ||
|
||||
fw_header->loader_revision != VIA_LOADER_REVISION) {
|
||||
WARNX(2, "%s is not a valid via firmware: version mismatch",
|
||||
@ -170,7 +146,7 @@ via_update(const char *dev, const char *path)
|
||||
}
|
||||
data_size = fw_header->data_size;
|
||||
total_size = fw_header->total_size;
|
||||
if (total_size > (unsigned)st.st_size || st.st_size < 0) {
|
||||
if (total_size > params->fwsize) {
|
||||
WARNX(2, "file too short: %s", path);
|
||||
goto fail;
|
||||
}
|
||||
@ -181,7 +157,7 @@ via_update(const char *dev, const char *path)
|
||||
*/
|
||||
sum = 0;
|
||||
for (i = 0; i < (payload_size / sizeof(uint32_t)); i++)
|
||||
sum += *((uint32_t *)fw_image + i);
|
||||
sum += *((const uint32_t *)fw_image + i);
|
||||
if (sum != 0) {
|
||||
WARNX(2, "%s: update data checksum invalid", path);
|
||||
goto fail;
|
||||
@ -202,25 +178,18 @@ via_update(const char *dev, const char *path)
|
||||
}
|
||||
fprintf(stderr, "%s: updating cpu %s from rev %#x to rev %#x... ",
|
||||
path, dev, revision, fw_header->revision);
|
||||
args.data = fw_data;
|
||||
args.data = __DECONST(void *, fw_data);
|
||||
args.size = data_size;
|
||||
error = ioctl(devfd, CPUCTL_UPDATE, &args);
|
||||
if (error < 0) {
|
||||
error = errno;
|
||||
fprintf(stderr, "failed.\n");
|
||||
fprintf(stderr, "failed.\n");
|
||||
errno = error;
|
||||
WARN(0, "ioctl()");
|
||||
goto fail;
|
||||
WARN(0, "ioctl()");
|
||||
goto fail;
|
||||
}
|
||||
fprintf(stderr, "done.\n");
|
||||
|
||||
fail:
|
||||
if (fw_image != MAP_FAILED)
|
||||
if (munmap(fw_image, st.st_size) != 0)
|
||||
warn("munmap(%s)", path);
|
||||
if (devfd >= 0)
|
||||
close(devfd);
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user