Fix the following error for armv7a-cros-linux-gnueabihf-clang.
sysfs_drv.c:247:49: error: incompatible pointer types passing 'uint64_t *' (aka
'unsigned long long *') to parameter of type 'size_t *'
(aka 'unsigned int *') [-Werror,-Wincompatible-pointer-types]
247 | if (!cbmem_sysfs_probe_cbmem_entry(id, &addr, &size))
| ^~~~~
sysfs_drv.c:99:84: note: passing argument to parameter 'size_out' here
99 | ...id, uint64_t *addr_out, size_t *size_out)
| ^
1 error generated.
BUG=b:434971585
TEST=none
BRANCH=none
Change-Id: I5e2be25d57c5e69501564b6e8b6d880ec046bc3b
Signed-off-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88605
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
266 lines
6.9 KiB
C
266 lines
6.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#include <errno.h>
|
|
#include <inttypes.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <dirent.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#if defined(__linux__) || defined(__ANDROID__)
|
|
#include <linux/fs.h>
|
|
#include <sys/ioctl.h>
|
|
#endif
|
|
|
|
#include <commonlib/bsd/cbmem_id.h>
|
|
#include <commonlib/bsd/ipchksum.h>
|
|
#include <commonlib/coreboot_tables.h>
|
|
#include <commonlib/helpers.h>
|
|
#include <commonlib/timestamp_serialized.h>
|
|
#include <commonlib/tpm_log_serialized.h>
|
|
|
|
#include "cbmem_util.h"
|
|
|
|
#define CBMEM_SYSFS_BASE_DIR "/sys/bus/coreboot/devices/"
|
|
#define CBMEM_SYSFS_ENTRY_DIR_NAME_PREFIX "cbmem-"
|
|
#define CBMEM_SYSFS_ENTRY_DIR_NAME_SCN_FMT CBMEM_SYSFS_ENTRY_DIR_NAME_PREFIX "%8" SCNx32
|
|
#define CBMEM_SYSFS_ENTRY_DIR_NAME_PRI_FMT CBMEM_SYSFS_ENTRY_DIR_NAME_PREFIX "%08" PRIx32
|
|
#define CBMEM_SYSFS_ENTRY_DIR_PATH_PRI_FMT \
|
|
CBMEM_SYSFS_BASE_DIR CBMEM_SYSFS_ENTRY_DIR_NAME_PRI_FMT
|
|
|
|
enum cbmem_sysfs_path_type {
|
|
CBMEM_SYSFS_PATH_BASE,
|
|
CBMEM_SYSFS_PATH_ADDRESS,
|
|
CBMEM_SYSFS_PATH_MEM,
|
|
CBMEM_SYSFS_PATH_SIZE,
|
|
};
|
|
|
|
/* Maximum filesystem path length. */
|
|
#define PATH_MAX_LEN 1024
|
|
|
|
/**
|
|
* Create new path for CBMEM entry of a requested type. free() path_out after use.
|
|
*
|
|
* @param id CBMEM_ID_* value.
|
|
* @param t path type.
|
|
* @param path_out output pointer to created path.
|
|
*/
|
|
static void new_sysfs_path(uint32_t id, enum cbmem_sysfs_path_type t, char *path_out, size_t path_out_max_size)
|
|
{
|
|
const char *const type2str[] = {
|
|
[CBMEM_SYSFS_PATH_BASE] = "",
|
|
[CBMEM_SYSFS_PATH_ADDRESS] = "/address",
|
|
[CBMEM_SYSFS_PATH_MEM] = "/mem",
|
|
[CBMEM_SYSFS_PATH_SIZE] = "/size"
|
|
};
|
|
|
|
if (t >= ARRAY_SIZE(type2str))
|
|
die("Incorrect path type requested: %d\n", t);
|
|
|
|
if (snprintf(path_out, path_out_max_size, CBMEM_SYSFS_ENTRY_DIR_PATH_PRI_FMT "%s", id,
|
|
type2str[t]) <= 0)
|
|
die("Unable to create sysfs path string for coreboot table: %#" PRIx32
|
|
". Path type: %d. Error: %s\n",
|
|
id, t, strerror(errno));
|
|
}
|
|
|
|
bool cbmem_sysfs_init(void)
|
|
{
|
|
char path[PATH_MAX_LEN];
|
|
|
|
for (enum cbmem_sysfs_path_type t = CBMEM_SYSFS_PATH_ADDRESS; t <= CBMEM_SYSFS_PATH_SIZE; ++t) {
|
|
new_sysfs_path(CBMEM_ID_CBTABLE, t, path, sizeof(path));
|
|
|
|
FILE *f = fopen(path, "rb");
|
|
if (!f) {
|
|
debug("Unable to open path %s for reading. Error: %s\n", path, strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
uint8_t test_byte = 0;
|
|
if (fread(&test_byte, 1, 1, f) != 1) {
|
|
debug("Unable to read data from %s. Error: %s\n", path, strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
fclose(f);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool cbmem_sysfs_probe_cbmem_entry(uint32_t id, uint64_t *addr_out, size_t *size_out)
|
|
{
|
|
char path[PATH_MAX_LEN];
|
|
|
|
new_sysfs_path(id, CBMEM_SYSFS_PATH_ADDRESS, path, sizeof(path));
|
|
|
|
FILE *address_file = fopen(path, "rb");
|
|
if (!address_file) {
|
|
debug("Unable to access CBMEM entry id: %#" PRIx32
|
|
" address file at %s. Error: %s\n",
|
|
id, path, strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
if (fscanf(address_file, "%" SCNx64, addr_out) != 1) {
|
|
debug("Read from %s failed.\n", path);
|
|
fclose(address_file);
|
|
return false;
|
|
}
|
|
fclose(address_file);
|
|
|
|
new_sysfs_path(id, CBMEM_SYSFS_PATH_SIZE, path, sizeof(path));
|
|
|
|
FILE *size_file = fopen(path, "rb");
|
|
if (!size_file) {
|
|
debug("Unable to access CBMEM entry id: %#" PRIx32
|
|
" size file at %s. Error: %s\n",
|
|
id, path, strerror(errno));
|
|
return false;
|
|
}
|
|
|
|
if (fscanf(size_file, "%zx", size_out) != 1) {
|
|
debug("Read from %s failed.\n", path);
|
|
fclose(size_file);
|
|
*addr_out = 0;
|
|
return false;
|
|
}
|
|
fclose(size_file);
|
|
|
|
return true;
|
|
}
|
|
|
|
static void fetch_cbmem_entry(const uint32_t id, const size_t size, uint8_t **buf_out)
|
|
{
|
|
char path[PATH_MAX_LEN];
|
|
|
|
new_sysfs_path(id, CBMEM_SYSFS_PATH_MEM, path, sizeof(path));
|
|
|
|
FILE *mem_file = fopen(path, "rb");
|
|
if (!mem_file)
|
|
die("Unable to open mem file for CBMEM entry id: %#" PRIx32
|
|
" at %s. Error: %s\n",
|
|
id, path, strerror(errno));
|
|
|
|
*buf_out = malloc(size);
|
|
if (!buf_out)
|
|
die("Unable to allocate memory for CBMEM entry id: %#" PRIx32
|
|
" of size: %zuB.\n",
|
|
id, size);
|
|
|
|
if (fread(*buf_out, 1, size, mem_file) != size)
|
|
die("Unable to correctly read memory of CBMEM entry id: %#" PRIx32
|
|
" at %s. Error: %s\n",
|
|
id, path, strerror(errno));
|
|
|
|
fclose(mem_file);
|
|
}
|
|
|
|
bool cbmem_sysfs_get_cbmem_entry(uint32_t id, uint8_t **buf_out, size_t *size_out, uint64_t *addr_out)
|
|
{
|
|
uint64_t addr;
|
|
size_t size;
|
|
|
|
if (!cbmem_sysfs_probe_cbmem_entry(id, &addr, &size)) {
|
|
debug("CBMEM entry id: %#" PRIx32 " not found.\n", id);
|
|
return false;
|
|
}
|
|
|
|
fetch_cbmem_entry(id, size, buf_out);
|
|
if (size_out)
|
|
*size_out = size;
|
|
if (addr_out)
|
|
*addr_out = addr;
|
|
return true;
|
|
}
|
|
|
|
bool cbmem_sysfs_write_cbmem_entry(uint32_t id, uint8_t *buf, size_t buf_size)
|
|
{
|
|
char path[PATH_MAX_LEN];
|
|
uint64_t addr;
|
|
size_t size;
|
|
|
|
if (!cbmem_sysfs_probe_cbmem_entry(id, &addr, &size)) {
|
|
debug("Unable to find CBMEM entry id: %#" PRIx32 "\n", id);
|
|
return false;
|
|
}
|
|
|
|
if (buf_size > size)
|
|
die("Attempting to write %zu bytes to CBMEM entry id: %#" PRIx32
|
|
" of %zu bytes. Operation not possible.\n",
|
|
buf_size, id, size);
|
|
|
|
new_sysfs_path(id, CBMEM_SYSFS_PATH_MEM, path, sizeof(path));
|
|
|
|
FILE *mem_file = fopen(path, "rb+");
|
|
if (!mem_file)
|
|
die("Unable to open mem file for CBMEM entry id: %#" PRIx32
|
|
" at %s. Error: %s\n",
|
|
id, path, strerror(errno));
|
|
|
|
if (fwrite(buf, 1, buf_size, mem_file) != buf_size)
|
|
die("Unable to correctly write memory of CBMEM entry id: %#" PRIx32
|
|
" at %s. Error: %s\n",
|
|
id, path, strerror(errno));
|
|
|
|
fclose(mem_file);
|
|
|
|
return true;
|
|
}
|
|
|
|
void cbmem_sysfs_foreach_cbmem_entry(cbmem_iterator_callback cb, void *data, bool with_contents)
|
|
{
|
|
DIR *dir;
|
|
struct dirent *entry;
|
|
|
|
if ((dir = opendir(CBMEM_SYSFS_BASE_DIR)) == NULL)
|
|
die("Unable to open directory containing CBMEM entries. Path: %s. Error: %s\n",
|
|
CBMEM_SYSFS_BASE_DIR, strerror(errno));
|
|
|
|
while ((entry = readdir(dir)) != NULL) {
|
|
debug("Checking path: %s%s\n", CBMEM_SYSFS_BASE_DIR, entry->d_name);
|
|
/* Check directory name prefix */
|
|
if (strncmp(entry->d_name, CBMEM_SYSFS_ENTRY_DIR_NAME_PREFIX,
|
|
strlen(CBMEM_SYSFS_ENTRY_DIR_NAME_PREFIX)) != 0)
|
|
continue;
|
|
|
|
uint32_t id = 0;
|
|
/* Extract CBMEM entry id from the directory name.
|
|
If it fails, then directory is not a correct entry. */
|
|
if (sscanf(entry->d_name, CBMEM_SYSFS_ENTRY_DIR_NAME_SCN_FMT, &id) != 1)
|
|
continue;
|
|
|
|
uint64_t addr = 0;
|
|
size_t size = 0;
|
|
uint8_t *buf;
|
|
|
|
/* If entry was not found or previously matched directory
|
|
does not contain necessary files, then omit the entry. */
|
|
if (!cbmem_sysfs_probe_cbmem_entry(id, &addr, &size))
|
|
continue;
|
|
|
|
if (with_contents)
|
|
fetch_cbmem_entry(id, size, &buf);
|
|
|
|
debug("Invoking callback on %s%s\n", CBMEM_SYSFS_BASE_DIR, entry->d_name);
|
|
|
|
const bool res = cb(id, addr, buf, size, data);
|
|
|
|
if (with_contents)
|
|
free(buf);
|
|
|
|
/* Finish iteration if callback requested it. */
|
|
if (res)
|
|
break;
|
|
}
|
|
|
|
closedir(dir);
|
|
}
|