95 lines
2.2 KiB
C
95 lines
2.2 KiB
C
|
/*
|
||
|
* coreboot_table.c
|
||
|
*
|
||
|
* Module providing coreboot table access.
|
||
|
*
|
||
|
* Copyright 2017 Google Inc.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License v2.0 as published by
|
||
|
* the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*/
|
||
|
|
||
|
#include <linux/err.h>
|
||
|
#include <linux/init.h>
|
||
|
#include <linux/io.h>
|
||
|
#include <linux/kernel.h>
|
||
|
#include <linux/module.h>
|
||
|
|
||
|
#include "coreboot_table.h"
|
||
|
|
||
|
struct coreboot_table_entry {
|
||
|
u32 tag;
|
||
|
u32 size;
|
||
|
};
|
||
|
|
||
|
static struct coreboot_table_header __iomem *ptr_header;
|
||
|
|
||
|
/*
|
||
|
* This function parses the coreboot table for an entry that contains the base
|
||
|
* address of the given entry tag. The coreboot table consists of a header
|
||
|
* directly followed by a number of small, variable-sized entries, which each
|
||
|
* contain an identifying tag and their length as the first two fields.
|
||
|
*/
|
||
|
int coreboot_table_find(int tag, void *data, size_t data_size)
|
||
|
{
|
||
|
struct coreboot_table_header header;
|
||
|
struct coreboot_table_entry entry;
|
||
|
void *ptr_entry;
|
||
|
int i;
|
||
|
|
||
|
if (!ptr_header)
|
||
|
return -EPROBE_DEFER;
|
||
|
|
||
|
memcpy_fromio(&header, ptr_header, sizeof(header));
|
||
|
|
||
|
if (strncmp(header.signature, "LBIO", sizeof(header.signature))) {
|
||
|
pr_warn("coreboot_table: coreboot table missing or corrupt!\n");
|
||
|
return -ENODEV;
|
||
|
}
|
||
|
|
||
|
ptr_entry = (void *)ptr_header + header.header_bytes;
|
||
|
|
||
|
for (i = 0; i < header.table_entries; i++) {
|
||
|
memcpy_fromio(&entry, ptr_entry, sizeof(entry));
|
||
|
if (entry.tag == tag) {
|
||
|
if (data_size < entry.size)
|
||
|
return -EINVAL;
|
||
|
|
||
|
memcpy_fromio(data, ptr_entry, entry.size);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
ptr_entry += entry.size;
|
||
|
}
|
||
|
|
||
|
return -ENOENT;
|
||
|
}
|
||
|
EXPORT_SYMBOL(coreboot_table_find);
|
||
|
|
||
|
int coreboot_table_init(void __iomem *ptr)
|
||
|
{
|
||
|
ptr_header = ptr;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
EXPORT_SYMBOL(coreboot_table_init);
|
||
|
|
||
|
int coreboot_table_exit(void)
|
||
|
{
|
||
|
if (ptr_header)
|
||
|
iounmap(ptr_header);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
EXPORT_SYMBOL(coreboot_table_exit);
|
||
|
|
||
|
MODULE_AUTHOR("Google, Inc.");
|
||
|
MODULE_LICENSE("GPL");
|