Remove something
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Christoph Hellwig <hch@lst.de>
|
||||
@@ -0,0 +1,2 @@
|
||||
*.c diff=cpp
|
||||
*.h diff=cpp
|
||||
-134
@@ -1,134 +0,0 @@
|
||||
#
|
||||
# NOTE! Don't add files that are generated in specific
|
||||
# subdirectories here. Add them in the ".gitignore" file
|
||||
# in that subdirectory instead.
|
||||
#
|
||||
# NOTE! Please use 'git ls-files -i --exclude-standard'
|
||||
# command after changing this file, to see if there are
|
||||
# any tracked files which get ignored after the change.
|
||||
#
|
||||
# Normal rules (sorted alphabetically)
|
||||
#
|
||||
.*
|
||||
*.a
|
||||
*.asn1.[ch]
|
||||
#*.bin
|
||||
*.bz2
|
||||
*.c.[012]*.*
|
||||
*.dtb
|
||||
*.dtb.S
|
||||
*.dwo
|
||||
*.elf
|
||||
*.gcno
|
||||
*.gz
|
||||
#*.i
|
||||
*.ko
|
||||
*.lex.c
|
||||
*.ll
|
||||
*.lst
|
||||
*.lz4
|
||||
*.lzma
|
||||
*.lzo
|
||||
*.mod.c
|
||||
*.o
|
||||
*.o.*
|
||||
*.order
|
||||
*.patch
|
||||
*.s
|
||||
*.so
|
||||
*.so.dbg
|
||||
*.su
|
||||
*.symtypes
|
||||
*.tab.[ch]
|
||||
*.tar
|
||||
*.xz
|
||||
Module.symvers
|
||||
modules.builtin
|
||||
|
||||
#
|
||||
# Top-level generic files
|
||||
#
|
||||
/tags
|
||||
/TAGS
|
||||
/linux
|
||||
/vmlinux
|
||||
/vmlinux.32
|
||||
/vmlinux-gdb.py
|
||||
/vmlinuz
|
||||
/System.map
|
||||
/Module.markers
|
||||
|
||||
#
|
||||
# RPM spec file (make rpm-pkg)
|
||||
#
|
||||
/*.spec
|
||||
|
||||
#
|
||||
# Debian directory (make deb-pkg)
|
||||
#
|
||||
/debian/
|
||||
|
||||
#
|
||||
# Snap directory (make snap-pkg)
|
||||
#
|
||||
/snap/
|
||||
|
||||
#
|
||||
# tar directory (make tar*-pkg)
|
||||
#
|
||||
/tar-install/
|
||||
|
||||
#
|
||||
# git files that we don't want to ignore even if they are dot-files
|
||||
#
|
||||
!.gitignore
|
||||
!.mailmap
|
||||
!.cocciconfig
|
||||
!.clang-format
|
||||
|
||||
#
|
||||
# Generated include files
|
||||
#
|
||||
include/config
|
||||
include/generated
|
||||
include/ksym
|
||||
arch/*/include/generated
|
||||
|
||||
# stgit generated dirs
|
||||
patches-*
|
||||
|
||||
# quilt's files
|
||||
patches
|
||||
series
|
||||
|
||||
# cscope files
|
||||
cscope.*
|
||||
ncscope.*
|
||||
|
||||
# gnu global files
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
|
||||
# id-utils files
|
||||
ID
|
||||
|
||||
*.orig
|
||||
*~
|
||||
\#*#
|
||||
|
||||
#
|
||||
# Leavings from module signing
|
||||
#
|
||||
extra_certificates
|
||||
signing_key.pem
|
||||
signing_key.priv
|
||||
signing_key.x509
|
||||
x509.genkey
|
||||
|
||||
# Kconfig presets
|
||||
all.config
|
||||
|
||||
# Kdevelop4
|
||||
*.kdev4
|
||||
@@ -0,0 +1,10 @@
|
||||
SECTIONS
|
||||
{
|
||||
.rodata..compressed : {
|
||||
input_len = .;
|
||||
LONG(input_data_end - input_data) input_data = .;
|
||||
*(.data)
|
||||
output_len = . - 4;
|
||||
input_data_end = .;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
zero_page_pos = .;
|
||||
*(.data)
|
||||
end_data = .;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# tools/power/acpi/tools/acpidbg/Makefile - ACPI tool Makefile
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation
|
||||
# Author: Lv Zheng <lv.zheng@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# of the License.
|
||||
|
||||
include ../../Makefile.config
|
||||
|
||||
TOOL = acpidbg
|
||||
vpath %.c \
|
||||
../../../../../drivers/acpi/acpica\
|
||||
../../common\
|
||||
../../os_specific/service_layers\
|
||||
.
|
||||
CFLAGS += -DACPI_APPLICATION -DACPI_SINGLE_THREAD -DACPI_DEBUGGER\
|
||||
-I.
|
||||
LDFLAGS += -lpthread
|
||||
TOOL_OBJS = \
|
||||
acpidbg.o
|
||||
|
||||
include ../../Makefile.rules
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* ACPI AML interfacing userspace utility
|
||||
*
|
||||
* Copyright (C) 2015, Intel Corporation
|
||||
* Authors: Lv Zheng <lv.zheng@intel.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
|
||||
/* Headers not included by include/acpi/platform/aclinux.h */
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <error.h>
|
||||
#include <stdbool.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <sys/select.h>
|
||||
#include "../../../../../include/linux/circ_buf.h"
|
||||
|
||||
#define ACPI_AML_FILE "/sys/kernel/debug/acpi/acpidbg"
|
||||
#define ACPI_AML_SEC_TICK 1
|
||||
#define ACPI_AML_USEC_PEEK 200
|
||||
#define ACPI_AML_BUF_SIZE 4096
|
||||
|
||||
#define ACPI_AML_BATCH_WRITE_CMD 0x00 /* Write command to kernel */
|
||||
#define ACPI_AML_BATCH_READ_LOG 0x01 /* Read log from kernel */
|
||||
#define ACPI_AML_BATCH_WRITE_LOG 0x02 /* Write log to console */
|
||||
|
||||
#define ACPI_AML_LOG_START 0x00
|
||||
#define ACPI_AML_PROMPT_START 0x01
|
||||
#define ACPI_AML_PROMPT_STOP 0x02
|
||||
#define ACPI_AML_LOG_STOP 0x03
|
||||
#define ACPI_AML_PROMPT_ROLL 0x04
|
||||
|
||||
#define ACPI_AML_INTERACTIVE 0x00
|
||||
#define ACPI_AML_BATCH 0x01
|
||||
|
||||
#define circ_count(circ) \
|
||||
(CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
|
||||
#define circ_count_to_end(circ) \
|
||||
(CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
|
||||
#define circ_space(circ) \
|
||||
(CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
|
||||
#define circ_space_to_end(circ) \
|
||||
(CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
|
||||
|
||||
#define acpi_aml_cmd_count() circ_count(&acpi_aml_cmd_crc)
|
||||
#define acpi_aml_log_count() circ_count(&acpi_aml_log_crc)
|
||||
#define acpi_aml_cmd_space() circ_space(&acpi_aml_cmd_crc)
|
||||
#define acpi_aml_log_space() circ_space(&acpi_aml_log_crc)
|
||||
|
||||
#define ACPI_AML_DO(_fd, _op, _buf, _ret) \
|
||||
do { \
|
||||
_ret = acpi_aml_##_op(_fd, &acpi_aml_##_buf##_crc); \
|
||||
if (_ret == 0) { \
|
||||
fprintf(stderr, \
|
||||
"%s %s pipe closed.\n", #_buf, #_op); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
#define ACPI_AML_BATCH_DO(_fd, _op, _buf, _ret) \
|
||||
do { \
|
||||
_ret = acpi_aml_##_op##_batch_##_buf(_fd, \
|
||||
&acpi_aml_##_buf##_crc); \
|
||||
if (_ret == 0) \
|
||||
return; \
|
||||
} while (0)
|
||||
|
||||
|
||||
static char acpi_aml_cmd_buf[ACPI_AML_BUF_SIZE];
|
||||
static char acpi_aml_log_buf[ACPI_AML_BUF_SIZE];
|
||||
static struct circ_buf acpi_aml_cmd_crc = {
|
||||
.buf = acpi_aml_cmd_buf,
|
||||
.head = 0,
|
||||
.tail = 0,
|
||||
};
|
||||
static struct circ_buf acpi_aml_log_crc = {
|
||||
.buf = acpi_aml_log_buf,
|
||||
.head = 0,
|
||||
.tail = 0,
|
||||
};
|
||||
static const char *acpi_aml_file_path = ACPI_AML_FILE;
|
||||
static unsigned long acpi_aml_mode = ACPI_AML_INTERACTIVE;
|
||||
static bool acpi_aml_exit;
|
||||
|
||||
static bool acpi_aml_batch_drain;
|
||||
static unsigned long acpi_aml_batch_state;
|
||||
static char acpi_aml_batch_prompt;
|
||||
static char acpi_aml_batch_roll;
|
||||
static unsigned long acpi_aml_log_state;
|
||||
static char *acpi_aml_batch_cmd = NULL;
|
||||
static char *acpi_aml_batch_pos = NULL;
|
||||
|
||||
static int acpi_aml_set_fl(int fd, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = fcntl(fd, F_GETFL, 0);
|
||||
if (ret < 0) {
|
||||
perror("fcntl(F_GETFL)");
|
||||
return ret;
|
||||
}
|
||||
flags |= ret;
|
||||
ret = fcntl(fd, F_SETFL, flags);
|
||||
if (ret < 0) {
|
||||
perror("fcntl(F_SETFL)");
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acpi_aml_set_fd(int fd, int maxfd, fd_set *set)
|
||||
{
|
||||
if (fd > maxfd)
|
||||
maxfd = fd;
|
||||
FD_SET(fd, set);
|
||||
return maxfd;
|
||||
}
|
||||
|
||||
static int acpi_aml_read(int fd, struct circ_buf *crc)
|
||||
{
|
||||
char *p;
|
||||
int len;
|
||||
|
||||
p = &crc->buf[crc->head];
|
||||
len = circ_space_to_end(crc);
|
||||
len = read(fd, p, len);
|
||||
if (len < 0)
|
||||
perror("read");
|
||||
else if (len > 0)
|
||||
crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int acpi_aml_read_batch_cmd(int unused, struct circ_buf *crc)
|
||||
{
|
||||
char *p;
|
||||
int len;
|
||||
int remained = strlen(acpi_aml_batch_pos);
|
||||
|
||||
p = &crc->buf[crc->head];
|
||||
len = circ_space_to_end(crc);
|
||||
if (len > remained) {
|
||||
memcpy(p, acpi_aml_batch_pos, remained);
|
||||
acpi_aml_batch_pos += remained;
|
||||
len = remained;
|
||||
} else {
|
||||
memcpy(p, acpi_aml_batch_pos, len);
|
||||
acpi_aml_batch_pos += len;
|
||||
}
|
||||
if (len > 0)
|
||||
crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int acpi_aml_read_batch_log(int fd, struct circ_buf *crc)
|
||||
{
|
||||
char *p;
|
||||
int len;
|
||||
int ret = 0;
|
||||
|
||||
p = &crc->buf[crc->head];
|
||||
len = circ_space_to_end(crc);
|
||||
while (ret < len && acpi_aml_log_state != ACPI_AML_LOG_STOP) {
|
||||
if (acpi_aml_log_state == ACPI_AML_PROMPT_ROLL) {
|
||||
*p = acpi_aml_batch_roll;
|
||||
len = 1;
|
||||
crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
|
||||
ret += 1;
|
||||
acpi_aml_log_state = ACPI_AML_LOG_START;
|
||||
} else {
|
||||
len = read(fd, p, 1);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
perror("read");
|
||||
ret = len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (acpi_aml_log_state) {
|
||||
case ACPI_AML_LOG_START:
|
||||
if (*p == '\n')
|
||||
acpi_aml_log_state = ACPI_AML_PROMPT_START;
|
||||
crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
|
||||
ret += 1;
|
||||
break;
|
||||
case ACPI_AML_PROMPT_START:
|
||||
if (*p == ACPI_DEBUGGER_COMMAND_PROMPT ||
|
||||
*p == ACPI_DEBUGGER_EXECUTE_PROMPT) {
|
||||
acpi_aml_batch_prompt = *p;
|
||||
acpi_aml_log_state = ACPI_AML_PROMPT_STOP;
|
||||
} else {
|
||||
if (*p != '\n')
|
||||
acpi_aml_log_state = ACPI_AML_LOG_START;
|
||||
crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
|
||||
ret += 1;
|
||||
}
|
||||
break;
|
||||
case ACPI_AML_PROMPT_STOP:
|
||||
if (*p == ' ') {
|
||||
acpi_aml_log_state = ACPI_AML_LOG_STOP;
|
||||
acpi_aml_exit = true;
|
||||
} else {
|
||||
/* Roll back */
|
||||
acpi_aml_log_state = ACPI_AML_PROMPT_ROLL;
|
||||
acpi_aml_batch_roll = *p;
|
||||
*p = acpi_aml_batch_prompt;
|
||||
crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
|
||||
ret += 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acpi_aml_write(int fd, struct circ_buf *crc)
|
||||
{
|
||||
char *p;
|
||||
int len;
|
||||
|
||||
p = &crc->buf[crc->tail];
|
||||
len = circ_count_to_end(crc);
|
||||
len = write(fd, p, len);
|
||||
if (len < 0)
|
||||
perror("write");
|
||||
else if (len > 0)
|
||||
crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int acpi_aml_write_batch_log(int fd, struct circ_buf *crc)
|
||||
{
|
||||
char *p;
|
||||
int len;
|
||||
|
||||
p = &crc->buf[crc->tail];
|
||||
len = circ_count_to_end(crc);
|
||||
if (!acpi_aml_batch_drain) {
|
||||
len = write(fd, p, len);
|
||||
if (len < 0)
|
||||
perror("write");
|
||||
}
|
||||
if (len > 0)
|
||||
crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int acpi_aml_write_batch_cmd(int fd, struct circ_buf *crc)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = acpi_aml_write(fd, crc);
|
||||
if (circ_count_to_end(crc) == 0)
|
||||
acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void acpi_aml_loop(int fd)
|
||||
{
|
||||
fd_set rfds;
|
||||
fd_set wfds;
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
int maxfd = 0;
|
||||
|
||||
if (acpi_aml_mode == ACPI_AML_BATCH) {
|
||||
acpi_aml_log_state = ACPI_AML_LOG_START;
|
||||
acpi_aml_batch_pos = acpi_aml_batch_cmd;
|
||||
if (acpi_aml_batch_drain)
|
||||
acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG;
|
||||
else
|
||||
acpi_aml_batch_state = ACPI_AML_BATCH_WRITE_CMD;
|
||||
}
|
||||
acpi_aml_exit = false;
|
||||
while (!acpi_aml_exit) {
|
||||
tv.tv_sec = ACPI_AML_SEC_TICK;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
|
||||
if (acpi_aml_cmd_space()) {
|
||||
if (acpi_aml_mode == ACPI_AML_INTERACTIVE)
|
||||
maxfd = acpi_aml_set_fd(STDIN_FILENO, maxfd, &rfds);
|
||||
else if (strlen(acpi_aml_batch_pos) &&
|
||||
acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD)
|
||||
ACPI_AML_BATCH_DO(STDIN_FILENO, read, cmd, ret);
|
||||
}
|
||||
if (acpi_aml_cmd_count() &&
|
||||
(acpi_aml_mode == ACPI_AML_INTERACTIVE ||
|
||||
acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD))
|
||||
maxfd = acpi_aml_set_fd(fd, maxfd, &wfds);
|
||||
if (acpi_aml_log_space() &&
|
||||
(acpi_aml_mode == ACPI_AML_INTERACTIVE ||
|
||||
acpi_aml_batch_state == ACPI_AML_BATCH_READ_LOG))
|
||||
maxfd = acpi_aml_set_fd(fd, maxfd, &rfds);
|
||||
if (acpi_aml_log_count())
|
||||
maxfd = acpi_aml_set_fd(STDOUT_FILENO, maxfd, &wfds);
|
||||
|
||||
ret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
|
||||
if (ret < 0) {
|
||||
perror("select");
|
||||
break;
|
||||
}
|
||||
if (ret > 0) {
|
||||
if (FD_ISSET(STDIN_FILENO, &rfds))
|
||||
ACPI_AML_DO(STDIN_FILENO, read, cmd, ret);
|
||||
if (FD_ISSET(fd, &wfds)) {
|
||||
if (acpi_aml_mode == ACPI_AML_BATCH)
|
||||
ACPI_AML_BATCH_DO(fd, write, cmd, ret);
|
||||
else
|
||||
ACPI_AML_DO(fd, write, cmd, ret);
|
||||
}
|
||||
if (FD_ISSET(fd, &rfds)) {
|
||||
if (acpi_aml_mode == ACPI_AML_BATCH)
|
||||
ACPI_AML_BATCH_DO(fd, read, log, ret);
|
||||
else
|
||||
ACPI_AML_DO(fd, read, log, ret);
|
||||
}
|
||||
if (FD_ISSET(STDOUT_FILENO, &wfds)) {
|
||||
if (acpi_aml_mode == ACPI_AML_BATCH)
|
||||
ACPI_AML_BATCH_DO(STDOUT_FILENO, write, log, ret);
|
||||
else
|
||||
ACPI_AML_DO(STDOUT_FILENO, write, log, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool acpi_aml_readable(int fd)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
int maxfd = 0;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = ACPI_AML_USEC_PEEK;
|
||||
FD_ZERO(&rfds);
|
||||
maxfd = acpi_aml_set_fd(fd, maxfd, &rfds);
|
||||
ret = select(maxfd+1, &rfds, NULL, NULL, &tv);
|
||||
if (ret < 0)
|
||||
perror("select");
|
||||
if (ret > 0 && FD_ISSET(fd, &rfds))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a userspace IO flush implementation, replying on the prompt
|
||||
* characters and can be turned into a flush() call after kernel implements
|
||||
* .flush() filesystem operation.
|
||||
*/
|
||||
static void acpi_aml_flush(int fd)
|
||||
{
|
||||
while (acpi_aml_readable(fd)) {
|
||||
acpi_aml_batch_drain = true;
|
||||
acpi_aml_loop(fd);
|
||||
acpi_aml_batch_drain = false;
|
||||
}
|
||||
}
|
||||
|
||||
void usage(FILE *file, char *progname)
|
||||
{
|
||||
fprintf(file, "usage: %s [-b cmd] [-f file] [-h]\n", progname);
|
||||
fprintf(file, "\nOptions:\n");
|
||||
fprintf(file, " -b Specify command to be executed in batch mode\n");
|
||||
fprintf(file, " -f Specify interface file other than");
|
||||
fprintf(file, " /sys/kernel/debug/acpi/acpidbg\n");
|
||||
fprintf(file, " -h Print this help message\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd = -1;
|
||||
int ch;
|
||||
int len;
|
||||
int ret = EXIT_SUCCESS;
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:f:h")) != -1) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
if (acpi_aml_batch_cmd) {
|
||||
fprintf(stderr, "Already specify %s\n",
|
||||
acpi_aml_batch_cmd);
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
len = strlen(optarg);
|
||||
acpi_aml_batch_cmd = calloc(len + 2, 1);
|
||||
if (!acpi_aml_batch_cmd) {
|
||||
perror("calloc");
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
memcpy(acpi_aml_batch_cmd, optarg, len);
|
||||
acpi_aml_batch_cmd[len] = '\n';
|
||||
acpi_aml_mode = ACPI_AML_BATCH;
|
||||
break;
|
||||
case 'f':
|
||||
acpi_aml_file_path = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage(stdout, argv[0]);
|
||||
goto exit;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage(stderr, argv[0]);
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fd = open(acpi_aml_file_path, O_RDWR | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
acpi_aml_set_fl(STDIN_FILENO, O_NONBLOCK);
|
||||
acpi_aml_set_fl(STDOUT_FILENO, O_NONBLOCK);
|
||||
|
||||
if (acpi_aml_mode == ACPI_AML_BATCH)
|
||||
acpi_aml_flush(fd);
|
||||
acpi_aml_loop(fd);
|
||||
|
||||
exit:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (acpi_aml_batch_cmd)
|
||||
free(acpi_aml_batch_cmd);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
# tools/power/acpi/tools/acpidump/Makefile - ACPI tool Makefile
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation
|
||||
# Author: Lv Zheng <lv.zheng@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# of the License.
|
||||
|
||||
include ../../Makefile.config
|
||||
|
||||
TOOL = acpidump
|
||||
EXTRA_INSTALL = install-man
|
||||
EXTRA_UNINSTALL = uninstall-man
|
||||
|
||||
vpath %.c \
|
||||
../../../../../drivers/acpi/acpica\
|
||||
./\
|
||||
../../common\
|
||||
../../os_specific/service_layers
|
||||
CFLAGS += -DACPI_DUMP_APP -I.
|
||||
TOOL_OBJS = \
|
||||
apdump.o\
|
||||
apfiles.o\
|
||||
apmain.o\
|
||||
osunixdir.o\
|
||||
osunixmap.o\
|
||||
osunixxf.o\
|
||||
tbprint.o\
|
||||
tbxfroot.o\
|
||||
utascii.o\
|
||||
utbuffer.o\
|
||||
utdebug.o\
|
||||
utexcep.o\
|
||||
utglobal.o\
|
||||
uthex.o\
|
||||
utmath.o\
|
||||
utnonansi.o\
|
||||
utprint.o\
|
||||
utstring.o\
|
||||
utstrsuppt.o\
|
||||
utstrtoul64.o\
|
||||
utxferror.o\
|
||||
oslinuxtbl.o\
|
||||
cmfsize.o\
|
||||
getopt.o
|
||||
|
||||
include ../../Makefile.rules
|
||||
|
||||
install-man: $(srctree)/man/acpidump.8
|
||||
$(ECHO) " INST " acpidump.8
|
||||
$(QUIET) $(INSTALL_DATA) -D $< $(DESTDIR)$(mandir)/man8/acpidump.8
|
||||
uninstall-man:
|
||||
$(ECHO) " UNINST " acpidump.8
|
||||
$(QUIET) rm -f $(DESTDIR)$(mandir)/man8/acpidump.8
|
||||
@@ -0,0 +1,85 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: acpidump.h - Include file for acpi_dump utility
|
||||
*
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Global variables. Defined in main.c only, externed in all other files
|
||||
*/
|
||||
#ifdef _DECLARE_GLOBALS
|
||||
#define EXTERN
|
||||
#define INIT_GLOBAL(a,b) a=b
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#define INIT_GLOBAL(a,b) a
|
||||
#endif
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "actables.h"
|
||||
#include "acapps.h"
|
||||
|
||||
/* Globals */
|
||||
|
||||
EXTERN u8 INIT_GLOBAL(gbl_summary_mode, FALSE);
|
||||
EXTERN u8 INIT_GLOBAL(gbl_verbose_mode, FALSE);
|
||||
EXTERN u8 INIT_GLOBAL(gbl_binary_mode, FALSE);
|
||||
EXTERN u8 INIT_GLOBAL(gbl_dump_customized_tables, TRUE);
|
||||
EXTERN u8 INIT_GLOBAL(gbl_do_not_dump_xsdt, FALSE);
|
||||
EXTERN ACPI_FILE INIT_GLOBAL(gbl_output_file, NULL);
|
||||
EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL);
|
||||
EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0);
|
||||
|
||||
/* Action table used to defer requested options */
|
||||
|
||||
struct ap_dump_action {
|
||||
char *argument;
|
||||
u32 to_be_done;
|
||||
};
|
||||
|
||||
#define AP_MAX_ACTIONS 32
|
||||
|
||||
#define AP_DUMP_ALL_TABLES 0
|
||||
#define AP_DUMP_TABLE_BY_ADDRESS 1
|
||||
#define AP_DUMP_TABLE_BY_NAME 2
|
||||
#define AP_DUMP_TABLE_BY_FILE 3
|
||||
|
||||
#define AP_MAX_ACPI_FILES 256 /* Prevent infinite loops */
|
||||
|
||||
/* Minimum FADT sizes for various table addresses */
|
||||
|
||||
#define MIN_FADT_FOR_DSDT (ACPI_FADT_OFFSET (dsdt) + sizeof (u32))
|
||||
#define MIN_FADT_FOR_FACS (ACPI_FADT_OFFSET (facs) + sizeof (u32))
|
||||
#define MIN_FADT_FOR_XDSDT (ACPI_FADT_OFFSET (Xdsdt) + sizeof (u64))
|
||||
#define MIN_FADT_FOR_XFACS (ACPI_FADT_OFFSET (Xfacs) + sizeof (u64))
|
||||
|
||||
/*
|
||||
* apdump - Table get/dump routines
|
||||
*/
|
||||
int ap_dump_table_from_file(char *pathname);
|
||||
|
||||
int ap_dump_table_by_name(char *signature);
|
||||
|
||||
int ap_dump_table_by_address(char *ascii_address);
|
||||
|
||||
int ap_dump_all_tables(void);
|
||||
|
||||
u8 ap_is_valid_header(struct acpi_table_header *table);
|
||||
|
||||
u8 ap_is_valid_checksum(struct acpi_table_header *table);
|
||||
|
||||
u32 ap_get_table_length(struct acpi_table_header *table);
|
||||
|
||||
/*
|
||||
* apfiles - File I/O utilities
|
||||
*/
|
||||
int ap_open_output_file(char *pathname);
|
||||
|
||||
int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance);
|
||||
|
||||
struct acpi_table_header *ap_get_table_from_file(char *pathname,
|
||||
u32 *file_size);
|
||||
@@ -0,0 +1,402 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: apdump - Dump routines for ACPI tables (acpidump)
|
||||
*
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "acpidump.h"
|
||||
|
||||
/* Local prototypes */
|
||||
|
||||
static int
|
||||
ap_dump_table_buffer(struct acpi_table_header *table,
|
||||
u32 instance, acpi_physical_address address);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_is_valid_header
|
||||
*
|
||||
* PARAMETERS: table - Pointer to table to be validated
|
||||
*
|
||||
* RETURN: TRUE if the header appears to be valid. FALSE otherwise
|
||||
*
|
||||
* DESCRIPTION: Check for a valid ACPI table header
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 ap_is_valid_header(struct acpi_table_header *table)
|
||||
{
|
||||
|
||||
if (!ACPI_VALIDATE_RSDP_SIG(table->signature)) {
|
||||
|
||||
/* Make sure signature is all ASCII and a valid ACPI name */
|
||||
|
||||
if (!acpi_ut_valid_nameseg(table->signature)) {
|
||||
fprintf(stderr,
|
||||
"Table signature (0x%8.8X) is invalid\n",
|
||||
*(u32 *)table->signature);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* Check for minimum table length */
|
||||
|
||||
if (table->length < sizeof(struct acpi_table_header)) {
|
||||
fprintf(stderr, "Table length (0x%8.8X) is invalid\n",
|
||||
table->length);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_is_valid_checksum
|
||||
*
|
||||
* PARAMETERS: table - Pointer to table to be validated
|
||||
*
|
||||
* RETURN: TRUE if the checksum appears to be valid. FALSE otherwise.
|
||||
*
|
||||
* DESCRIPTION: Check for a valid ACPI table checksum.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8 ap_is_valid_checksum(struct acpi_table_header *table)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_table_rsdp *rsdp;
|
||||
|
||||
if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
|
||||
/*
|
||||
* Checksum for RSDP.
|
||||
* Note: Other checksums are computed during the table dump.
|
||||
*/
|
||||
rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
|
||||
status = acpi_tb_validate_rsdp(rsdp);
|
||||
} else {
|
||||
status = acpi_tb_verify_checksum(table, table->length);
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n",
|
||||
table->signature);
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_get_table_length
|
||||
*
|
||||
* PARAMETERS: table - Pointer to the table
|
||||
*
|
||||
* RETURN: Table length
|
||||
*
|
||||
* DESCRIPTION: Obtain table length according to table signature.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u32 ap_get_table_length(struct acpi_table_header *table)
|
||||
{
|
||||
struct acpi_table_rsdp *rsdp;
|
||||
|
||||
/* Check if table is valid */
|
||||
|
||||
if (!ap_is_valid_header(table)) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
|
||||
rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
|
||||
return (acpi_tb_get_rsdp_length(rsdp));
|
||||
}
|
||||
|
||||
/* Normal ACPI table */
|
||||
|
||||
return (table->length);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_dump_table_buffer
|
||||
*
|
||||
* PARAMETERS: table - ACPI table to be dumped
|
||||
* instance - ACPI table instance no. to be dumped
|
||||
* address - Physical address of the table
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a
|
||||
* header that is compatible with the acpi_xtract utility.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static int
|
||||
ap_dump_table_buffer(struct acpi_table_header *table,
|
||||
u32 instance, acpi_physical_address address)
|
||||
{
|
||||
u32 table_length;
|
||||
|
||||
table_length = ap_get_table_length(table);
|
||||
|
||||
/* Print only the header if requested */
|
||||
|
||||
if (gbl_summary_mode) {
|
||||
acpi_tb_print_table_header(address, table);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Dump to binary file if requested */
|
||||
|
||||
if (gbl_binary_mode) {
|
||||
return (ap_write_to_binary_file(table, instance));
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the table with header for use with acpixtract utility.
|
||||
* Note: simplest to just always emit a 64-bit address. acpi_xtract
|
||||
* utility can handle this.
|
||||
*/
|
||||
fprintf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n",
|
||||
table->signature, ACPI_FORMAT_UINT64(address));
|
||||
|
||||
acpi_ut_dump_buffer_to_file(gbl_output_file,
|
||||
ACPI_CAST_PTR(u8, table), table_length,
|
||||
DB_BYTE_DISPLAY, 0);
|
||||
fprintf(gbl_output_file, "\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_dump_all_tables
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the
|
||||
* tables that we can possibly get).
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int ap_dump_all_tables(void)
|
||||
{
|
||||
struct acpi_table_header *table;
|
||||
u32 instance = 0;
|
||||
acpi_physical_address address;
|
||||
acpi_status status;
|
||||
int table_status;
|
||||
u32 i;
|
||||
|
||||
/* Get and dump all available ACPI tables */
|
||||
|
||||
for (i = 0; i < AP_MAX_ACPI_FILES; i++) {
|
||||
status =
|
||||
acpi_os_get_table_by_index(i, &table, &instance, &address);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* AE_LIMIT means that no more tables are available */
|
||||
|
||||
if (status == AE_LIMIT) {
|
||||
return (0);
|
||||
} else if (i == 0) {
|
||||
fprintf(stderr,
|
||||
"Could not get ACPI tables, %s\n",
|
||||
acpi_format_exception(status));
|
||||
return (-1);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Could not get ACPI table at index %u, %s\n",
|
||||
i, acpi_format_exception(status));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
table_status = ap_dump_table_buffer(table, instance, address);
|
||||
ACPI_FREE(table);
|
||||
|
||||
if (table_status) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Something seriously bad happened if the loop terminates here */
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_dump_table_by_address
|
||||
*
|
||||
* PARAMETERS: ascii_address - Address for requested ACPI table
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Get an ACPI table via a physical address and dump it.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int ap_dump_table_by_address(char *ascii_address)
|
||||
{
|
||||
acpi_physical_address address;
|
||||
struct acpi_table_header *table;
|
||||
acpi_status status;
|
||||
int table_status;
|
||||
u64 long_address;
|
||||
|
||||
/* Convert argument to an integer physical address */
|
||||
|
||||
status = acpi_ut_strtoul64(ascii_address, &long_address);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
fprintf(stderr, "%s: Could not convert to a physical address\n",
|
||||
ascii_address);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
address = (acpi_physical_address)long_address;
|
||||
status = acpi_os_get_table_by_address(address, &table);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n",
|
||||
ACPI_FORMAT_UINT64(address),
|
||||
acpi_format_exception(status));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
table_status = ap_dump_table_buffer(table, 0, address);
|
||||
ACPI_FREE(table);
|
||||
return (table_status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_dump_table_by_name
|
||||
*
|
||||
* PARAMETERS: signature - Requested ACPI table signature
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Get an ACPI table via a signature and dump it. Handles
|
||||
* multiple tables with the same signature (SSDTs).
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int ap_dump_table_by_name(char *signature)
|
||||
{
|
||||
char local_signature[ACPI_NAME_SIZE + 1];
|
||||
u32 instance;
|
||||
struct acpi_table_header *table;
|
||||
acpi_physical_address address;
|
||||
acpi_status status;
|
||||
int table_status;
|
||||
|
||||
if (strlen(signature) != ACPI_NAME_SIZE) {
|
||||
fprintf(stderr,
|
||||
"Invalid table signature [%s]: must be exactly 4 characters\n",
|
||||
signature);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Table signatures are expected to be uppercase */
|
||||
|
||||
strcpy(local_signature, signature);
|
||||
acpi_ut_strupr(local_signature);
|
||||
|
||||
/* To be friendly, handle tables whose signatures do not match the name */
|
||||
|
||||
if (ACPI_COMPARE_NAME(local_signature, "FADT")) {
|
||||
strcpy(local_signature, ACPI_SIG_FADT);
|
||||
} else if (ACPI_COMPARE_NAME(local_signature, "MADT")) {
|
||||
strcpy(local_signature, ACPI_SIG_MADT);
|
||||
}
|
||||
|
||||
/* Dump all instances of this signature (to handle multiple SSDTs) */
|
||||
|
||||
for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) {
|
||||
status = acpi_os_get_table_by_name(local_signature, instance,
|
||||
&table, &address);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* AE_LIMIT means that no more tables are available */
|
||||
|
||||
if (status == AE_LIMIT) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"Could not get ACPI table with signature [%s], %s\n",
|
||||
local_signature, acpi_format_exception(status));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
table_status = ap_dump_table_buffer(table, instance, address);
|
||||
ACPI_FREE(table);
|
||||
|
||||
if (table_status) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Something seriously bad happened if the loop terminates here */
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_dump_table_from_file
|
||||
*
|
||||
* PARAMETERS: pathname - File containing the binary ACPI table
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Dump an ACPI table from a binary file
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int ap_dump_table_from_file(char *pathname)
|
||||
{
|
||||
struct acpi_table_header *table;
|
||||
u32 file_size = 0;
|
||||
int table_status = -1;
|
||||
|
||||
/* Get the entire ACPI table from the file */
|
||||
|
||||
table = ap_get_table_from_file(pathname, &file_size);
|
||||
if (!table) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!acpi_ut_valid_nameseg(table->signature)) {
|
||||
fprintf(stderr,
|
||||
"No valid ACPI signature was found in input file %s\n",
|
||||
pathname);
|
||||
}
|
||||
|
||||
/* File must be at least as long as the table length */
|
||||
|
||||
if (table->length > file_size) {
|
||||
fprintf(stderr,
|
||||
"Table length (0x%X) is too large for input file (0x%X) %s\n",
|
||||
table->length, file_size, pathname);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (gbl_verbose_mode) {
|
||||
fprintf(stderr,
|
||||
"Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n",
|
||||
pathname, table->signature, file_size, file_size);
|
||||
}
|
||||
|
||||
table_status = ap_dump_table_buffer(table, 0, 0);
|
||||
|
||||
exit:
|
||||
ACPI_FREE(table);
|
||||
return (table_status);
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: apfiles - File-related functions for acpidump utility
|
||||
*
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "acpidump.h"
|
||||
|
||||
/* Local prototypes */
|
||||
|
||||
static int ap_is_existing_file(char *pathname);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_is_existing_file
|
||||
*
|
||||
* PARAMETERS: pathname - Output filename
|
||||
*
|
||||
* RETURN: 0 on success
|
||||
*
|
||||
* DESCRIPTION: Query for file overwrite if it already exists.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static int ap_is_existing_file(char *pathname)
|
||||
{
|
||||
#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
|
||||
struct stat stat_info;
|
||||
|
||||
if (!stat(pathname, &stat_info)) {
|
||||
fprintf(stderr,
|
||||
"Target path already exists, overwrite? [y|n] ");
|
||||
|
||||
if (getchar() != 'y') {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_open_output_file
|
||||
*
|
||||
* PARAMETERS: pathname - Output filename
|
||||
*
|
||||
* RETURN: Open file handle
|
||||
*
|
||||
* DESCRIPTION: Open a text output file for acpidump. Checks if file already
|
||||
* exists.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int ap_open_output_file(char *pathname)
|
||||
{
|
||||
ACPI_FILE file;
|
||||
|
||||
/* If file exists, prompt for overwrite */
|
||||
|
||||
if (ap_is_existing_file(pathname) != 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Point stdout to the file */
|
||||
|
||||
file = fopen(pathname, "w");
|
||||
if (!file) {
|
||||
fprintf(stderr, "Could not open output file: %s\n", pathname);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Save the file and path */
|
||||
|
||||
gbl_output_file = file;
|
||||
gbl_output_filename = pathname;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_write_to_binary_file
|
||||
*
|
||||
* PARAMETERS: table - ACPI table to be written
|
||||
* instance - ACPI table instance no. to be written
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Write an ACPI table to a binary file. Builds the output
|
||||
* filename from the table signature.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
|
||||
{
|
||||
char filename[ACPI_NAME_SIZE + 16];
|
||||
char instance_str[16];
|
||||
ACPI_FILE file;
|
||||
acpi_size actual;
|
||||
u32 table_length;
|
||||
|
||||
/* Obtain table length */
|
||||
|
||||
table_length = ap_get_table_length(table);
|
||||
|
||||
/* Construct lower-case filename from the table local signature */
|
||||
|
||||
if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
|
||||
ACPI_MOVE_NAME(filename, ACPI_RSDP_NAME);
|
||||
} else {
|
||||
ACPI_MOVE_NAME(filename, table->signature);
|
||||
}
|
||||
|
||||
filename[0] = (char)tolower((int)filename[0]);
|
||||
filename[1] = (char)tolower((int)filename[1]);
|
||||
filename[2] = (char)tolower((int)filename[2]);
|
||||
filename[3] = (char)tolower((int)filename[3]);
|
||||
filename[ACPI_NAME_SIZE] = 0;
|
||||
|
||||
/* Handle multiple SSDts - create different filenames for each */
|
||||
|
||||
if (instance > 0) {
|
||||
snprintf(instance_str, sizeof(instance_str), "%u", instance);
|
||||
strcat(filename, instance_str);
|
||||
}
|
||||
|
||||
strcat(filename, FILE_SUFFIX_BINARY_TABLE);
|
||||
|
||||
if (gbl_verbose_mode) {
|
||||
fprintf(stderr,
|
||||
"Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n",
|
||||
table->signature, filename, table->length,
|
||||
table->length);
|
||||
}
|
||||
|
||||
/* Open the file and dump the entire table in binary mode */
|
||||
|
||||
file = fopen(filename, "wb");
|
||||
if (!file) {
|
||||
fprintf(stderr, "Could not open output file: %s\n", filename);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
actual = fwrite(table, 1, table_length, file);
|
||||
if (actual != table_length) {
|
||||
fprintf(stderr, "Error writing binary output file: %s\n",
|
||||
filename);
|
||||
fclose(file);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_get_table_from_file
|
||||
*
|
||||
* PARAMETERS: pathname - File containing the binary ACPI table
|
||||
* out_file_size - Where the file size is returned
|
||||
*
|
||||
* RETURN: Buffer containing the ACPI table. NULL on error.
|
||||
*
|
||||
* DESCRIPTION: Open a file and read it entirely into a new buffer
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
struct acpi_table_header *ap_get_table_from_file(char *pathname,
|
||||
u32 *out_file_size)
|
||||
{
|
||||
struct acpi_table_header *buffer = NULL;
|
||||
ACPI_FILE file;
|
||||
u32 file_size;
|
||||
acpi_size actual;
|
||||
|
||||
/* Must use binary mode */
|
||||
|
||||
file = fopen(pathname, "rb");
|
||||
if (!file) {
|
||||
fprintf(stderr, "Could not open input file: %s\n", pathname);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Need file size to allocate a buffer */
|
||||
|
||||
file_size = cm_get_file_size(file);
|
||||
if (file_size == ACPI_UINT32_MAX) {
|
||||
fprintf(stderr,
|
||||
"Could not get input file size: %s\n", pathname);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Allocate a buffer for the entire file */
|
||||
|
||||
buffer = ACPI_ALLOCATE_ZEROED(file_size);
|
||||
if (!buffer) {
|
||||
fprintf(stderr,
|
||||
"Could not allocate file buffer of size: %u\n",
|
||||
file_size);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Read the entire file */
|
||||
|
||||
actual = fread(buffer, 1, file_size, file);
|
||||
if (actual != file_size) {
|
||||
fprintf(stderr, "Could not read input file: %s\n", pathname);
|
||||
ACPI_FREE(buffer);
|
||||
buffer = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*out_file_size = file_size;
|
||||
|
||||
cleanup:
|
||||
fclose(file);
|
||||
return (buffer);
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: apmain - Main module for the acpidump utility
|
||||
*
|
||||
* Copyright (C) 2000 - 2018, Intel Corp.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#define _DECLARE_GLOBALS
|
||||
#include "acpidump.h"
|
||||
|
||||
/*
|
||||
* acpidump - A portable utility for obtaining system ACPI tables and dumping
|
||||
* them in an ASCII hex format suitable for binary extraction via acpixtract.
|
||||
*
|
||||
* Obtaining the system ACPI tables is an OS-specific operation.
|
||||
*
|
||||
* This utility can be ported to any host operating system by providing a
|
||||
* module containing system-specific versions of these interfaces:
|
||||
*
|
||||
* acpi_os_get_table_by_address
|
||||
* acpi_os_get_table_by_index
|
||||
* acpi_os_get_table_by_name
|
||||
*
|
||||
* See the ACPICA Reference Guide for the exact definitions of these
|
||||
* interfaces. Also, see these ACPICA source code modules for example
|
||||
* implementations:
|
||||
*
|
||||
* source/os_specific/service_layers/oswintbl.c
|
||||
* source/os_specific/service_layers/oslinuxtbl.c
|
||||
*/
|
||||
|
||||
/* Local prototypes */
|
||||
|
||||
static void ap_display_usage(void);
|
||||
|
||||
static int ap_do_options(int argc, char **argv);
|
||||
|
||||
static int ap_insert_action(char *argument, u32 to_be_done);
|
||||
|
||||
/* Table for deferred actions from command line options */
|
||||
|
||||
struct ap_dump_action action_table[AP_MAX_ACTIONS];
|
||||
u32 current_action = 0;
|
||||
|
||||
#define AP_UTILITY_NAME "ACPI Binary Table Dump Utility"
|
||||
#define AP_SUPPORTED_OPTIONS "?a:bc:f:hn:o:r:sv^xz"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_display_usage
|
||||
*
|
||||
* DESCRIPTION: Usage message for the acpi_dump utility
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void ap_display_usage(void)
|
||||
{
|
||||
|
||||
ACPI_USAGE_HEADER("acpidump [options]");
|
||||
|
||||
ACPI_OPTION("-b", "Dump tables to binary files");
|
||||
ACPI_OPTION("-h -?", "This help message");
|
||||
ACPI_OPTION("-o <File>", "Redirect output to file");
|
||||
ACPI_OPTION("-r <Address>", "Dump tables from specified RSDP");
|
||||
ACPI_OPTION("-s", "Print table summaries only");
|
||||
ACPI_OPTION("-v", "Display version information");
|
||||
ACPI_OPTION("-vd", "Display build date and time");
|
||||
ACPI_OPTION("-z", "Verbose mode");
|
||||
|
||||
ACPI_USAGE_TEXT("\nTable Options:\n");
|
||||
|
||||
ACPI_OPTION("-a <Address>", "Get table via a physical address");
|
||||
ACPI_OPTION("-c <on|off>", "Turning on/off customized table dumping");
|
||||
ACPI_OPTION("-f <BinaryFile>", "Get table via a binary file");
|
||||
ACPI_OPTION("-n <Signature>", "Get table via a name/signature");
|
||||
ACPI_OPTION("-x", "Do not use but dump XSDT");
|
||||
ACPI_OPTION("-x -x", "Do not use or dump XSDT");
|
||||
|
||||
ACPI_USAGE_TEXT("\n"
|
||||
"Invocation without parameters dumps all available tables\n"
|
||||
"Multiple mixed instances of -a, -f, and -n are supported\n\n");
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_insert_action
|
||||
*
|
||||
* PARAMETERS: argument - Pointer to the argument for this action
|
||||
* to_be_done - What to do to process this action
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Add an action item to the action table
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static int ap_insert_action(char *argument, u32 to_be_done)
|
||||
{
|
||||
|
||||
/* Insert action and check for table overflow */
|
||||
|
||||
action_table[current_action].argument = argument;
|
||||
action_table[current_action].to_be_done = to_be_done;
|
||||
|
||||
current_action++;
|
||||
if (current_action > AP_MAX_ACTIONS) {
|
||||
fprintf(stderr, "Too many table options (max %d)\n",
|
||||
AP_MAX_ACTIONS);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: ap_do_options
|
||||
*
|
||||
* PARAMETERS: argc/argv - Standard argc/argv
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Command line option processing. The main actions for getting
|
||||
* and dumping tables are deferred via the action table.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static int ap_do_options(int argc, char **argv)
|
||||
{
|
||||
int j;
|
||||
acpi_status status;
|
||||
|
||||
/* Command line options */
|
||||
|
||||
while ((j =
|
||||
acpi_getopt(argc, argv, AP_SUPPORTED_OPTIONS)) != ACPI_OPT_END)
|
||||
switch (j) {
|
||||
/*
|
||||
* Global options
|
||||
*/
|
||||
case 'b': /* Dump all input tables to binary files */
|
||||
|
||||
gbl_binary_mode = TRUE;
|
||||
continue;
|
||||
|
||||
case 'c': /* Dump customized tables */
|
||||
|
||||
if (!strcmp(acpi_gbl_optarg, "on")) {
|
||||
gbl_dump_customized_tables = TRUE;
|
||||
} else if (!strcmp(acpi_gbl_optarg, "off")) {
|
||||
gbl_dump_customized_tables = FALSE;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"%s: Cannot handle this switch, please use on|off\n",
|
||||
acpi_gbl_optarg);
|
||||
return (-1);
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
|
||||
ap_display_usage();
|
||||
return (1);
|
||||
|
||||
case 'o': /* Redirect output to a single file */
|
||||
|
||||
if (ap_open_output_file(acpi_gbl_optarg)) {
|
||||
return (-1);
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'r': /* Dump tables from specified RSDP */
|
||||
|
||||
status =
|
||||
acpi_ut_strtoul64(acpi_gbl_optarg, &gbl_rsdp_base);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
fprintf(stderr,
|
||||
"%s: Could not convert to a physical address\n",
|
||||
acpi_gbl_optarg);
|
||||
return (-1);
|
||||
}
|
||||
continue;
|
||||
|
||||
case 's': /* Print table summaries only */
|
||||
|
||||
gbl_summary_mode = TRUE;
|
||||
continue;
|
||||
|
||||
case 'x': /* Do not use XSDT */
|
||||
|
||||
if (!acpi_gbl_do_not_use_xsdt) {
|
||||
acpi_gbl_do_not_use_xsdt = TRUE;
|
||||
} else {
|
||||
gbl_do_not_dump_xsdt = TRUE;
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'v': /* -v: (Version): signon already emitted, just exit */
|
||||
|
||||
switch (acpi_gbl_optarg[0]) {
|
||||
case '^': /* -v: (Version) */
|
||||
|
||||
fprintf(stderr,
|
||||
ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
|
||||
return (1);
|
||||
|
||||
case 'd':
|
||||
|
||||
fprintf(stderr,
|
||||
ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
|
||||
printf(ACPI_COMMON_BUILD_TIME);
|
||||
return (1);
|
||||
|
||||
default:
|
||||
|
||||
printf("Unknown option: -v%s\n",
|
||||
acpi_gbl_optarg);
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'z': /* Verbose mode */
|
||||
|
||||
gbl_verbose_mode = TRUE;
|
||||
fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Table options
|
||||
*/
|
||||
case 'a': /* Get table by physical address */
|
||||
|
||||
if (ap_insert_action
|
||||
(acpi_gbl_optarg, AP_DUMP_TABLE_BY_ADDRESS)) {
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f': /* Get table from a file */
|
||||
|
||||
if (ap_insert_action
|
||||
(acpi_gbl_optarg, AP_DUMP_TABLE_BY_FILE)) {
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n': /* Get table by input name (signature) */
|
||||
|
||||
if (ap_insert_action
|
||||
(acpi_gbl_optarg, AP_DUMP_TABLE_BY_NAME)) {
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
ap_display_usage();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* If there are no actions, this means "get/dump all tables" */
|
||||
|
||||
if (current_action == 0) {
|
||||
if (ap_insert_action(NULL, AP_DUMP_ALL_TABLES)) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: main
|
||||
*
|
||||
* PARAMETERS: argc/argv - Standard argc/argv
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: C main function for acpidump utility
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
|
||||
int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
|
||||
#else
|
||||
int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int status = 0;
|
||||
struct ap_dump_action *action;
|
||||
u32 file_size;
|
||||
u32 i;
|
||||
|
||||
ACPI_DEBUG_INITIALIZE(); /* For debug version only */
|
||||
acpi_os_initialize();
|
||||
gbl_output_file = ACPI_FILE_OUT;
|
||||
acpi_gbl_integer_byte_width = 8;
|
||||
|
||||
/* Process command line options */
|
||||
|
||||
status = ap_do_options(argc, argv);
|
||||
if (status > 0) {
|
||||
return (0);
|
||||
}
|
||||
if (status < 0) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
/* Get/dump ACPI table(s) as requested */
|
||||
|
||||
for (i = 0; i < current_action; i++) {
|
||||
action = &action_table[i];
|
||||
switch (action->to_be_done) {
|
||||
case AP_DUMP_ALL_TABLES:
|
||||
|
||||
status = ap_dump_all_tables();
|
||||
break;
|
||||
|
||||
case AP_DUMP_TABLE_BY_ADDRESS:
|
||||
|
||||
status = ap_dump_table_by_address(action->argument);
|
||||
break;
|
||||
|
||||
case AP_DUMP_TABLE_BY_NAME:
|
||||
|
||||
status = ap_dump_table_by_name(action->argument);
|
||||
break;
|
||||
|
||||
case AP_DUMP_TABLE_BY_FILE:
|
||||
|
||||
status = ap_dump_table_from_file(action->argument);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
fprintf(stderr,
|
||||
"Internal error, invalid action: 0x%X\n",
|
||||
action->to_be_done);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
return (status);
|
||||
}
|
||||
}
|
||||
|
||||
if (gbl_output_filename) {
|
||||
if (gbl_verbose_mode) {
|
||||
|
||||
/* Summary for the output file */
|
||||
|
||||
file_size = cm_get_file_size(gbl_output_file);
|
||||
fprintf(stderr,
|
||||
"Output file %s contains 0x%X (%u) bytes\n\n",
|
||||
gbl_output_filename, file_size, file_size);
|
||||
}
|
||||
|
||||
fclose(gbl_output_file);
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# tools/power/acpi/tools/acpidump/Makefile - ACPI tool Makefile
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation
|
||||
# Author: Lv Zheng <lv.zheng@intel.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; version 2
|
||||
# of the License.
|
||||
|
||||
include ../../Makefile.config
|
||||
|
||||
TOOL = ec
|
||||
TOOL_OBJS = \
|
||||
ec_access.o
|
||||
|
||||
include ../../Makefile.rules
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* ec_access.c
|
||||
*
|
||||
* Copyright (C) 2010 SUSE Linux Products GmbH
|
||||
* Author:
|
||||
* Thomas Renninger <trenn@suse.de>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#define EC_SPACE_SIZE 256
|
||||
#define SYSFS_PATH "/sys/kernel/debug/ec/ec0/io"
|
||||
|
||||
/* TBD/Enhancements:
|
||||
- Provide param for accessing different ECs (not supported by kernel yet)
|
||||
*/
|
||||
|
||||
static int read_mode = -1;
|
||||
static int sleep_time;
|
||||
static int write_byte_offset = -1;
|
||||
static int read_byte_offset = -1;
|
||||
static uint8_t write_value = -1;
|
||||
|
||||
void usage(char progname[], int exit_status)
|
||||
{
|
||||
printf("Usage:\n");
|
||||
printf("1) %s -r [-s sleep]\n", basename(progname));
|
||||
printf("2) %s -b byte_offset\n", basename(progname));
|
||||
printf("3) %s -w byte_offset -v value\n\n", basename(progname));
|
||||
|
||||
puts("\t-r [-s sleep] : Dump EC registers");
|
||||
puts("\t If sleep is given, sleep x seconds,");
|
||||
puts("\t re-read EC registers and show changes");
|
||||
puts("\t-b offset : Read value at byte_offset (in hex)");
|
||||
puts("\t-w offset -v value : Write value at byte_offset");
|
||||
puts("\t-h : Print this help\n\n");
|
||||
puts("Offsets and values are in hexadecimal number system.");
|
||||
puts("The offset and value must be between 0 and 0xff.");
|
||||
exit(exit_status);
|
||||
}
|
||||
|
||||
void parse_opts(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "rs:b:w:v:h")) != -1) {
|
||||
|
||||
switch (c) {
|
||||
case 'r':
|
||||
if (read_mode != -1)
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
read_mode = 1;
|
||||
break;
|
||||
case 's':
|
||||
if (read_mode != -1 && read_mode != 1)
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
|
||||
sleep_time = atoi(optarg);
|
||||
if (sleep_time <= 0) {
|
||||
sleep_time = 0;
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
printf("Bad sleep time: %s\n", optarg);
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
if (read_mode != -1)
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
read_mode = 1;
|
||||
read_byte_offset = strtoul(optarg, NULL, 16);
|
||||
break;
|
||||
case 'w':
|
||||
if (read_mode != -1)
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
read_mode = 0;
|
||||
write_byte_offset = strtoul(optarg, NULL, 16);
|
||||
break;
|
||||
case 'v':
|
||||
write_value = strtoul(optarg, NULL, 16);
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0], EXIT_SUCCESS);
|
||||
default:
|
||||
fprintf(stderr, "Unknown option!\n");
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (read_mode == 0) {
|
||||
if (write_byte_offset < 0 ||
|
||||
write_byte_offset >= EC_SPACE_SIZE) {
|
||||
fprintf(stderr, "Wrong byte offset 0x%.2x, valid: "
|
||||
"[0-0x%.2x]\n",
|
||||
write_byte_offset, EC_SPACE_SIZE - 1);
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
}
|
||||
if (write_value < 0 ||
|
||||
write_value >= 255) {
|
||||
fprintf(stderr, "Wrong byte offset 0x%.2x, valid:"
|
||||
"[0-0xff]\n", write_byte_offset);
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (read_mode == 1 && read_byte_offset != -1) {
|
||||
if (read_byte_offset < -1 ||
|
||||
read_byte_offset >= EC_SPACE_SIZE) {
|
||||
fprintf(stderr, "Wrong byte offset 0x%.2x, valid: "
|
||||
"[0-0x%.2x]\n",
|
||||
read_byte_offset, EC_SPACE_SIZE - 1);
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
/* Add additional parameter checks here */
|
||||
}
|
||||
|
||||
void dump_ec(int fd)
|
||||
{
|
||||
char buf[EC_SPACE_SIZE];
|
||||
char buf2[EC_SPACE_SIZE];
|
||||
int byte_off, bytes_read;
|
||||
|
||||
bytes_read = read(fd, buf, EC_SPACE_SIZE);
|
||||
|
||||
if (bytes_read == -1)
|
||||
err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH);
|
||||
|
||||
if (bytes_read != EC_SPACE_SIZE)
|
||||
fprintf(stderr, "Could only read %d bytes\n", bytes_read);
|
||||
|
||||
printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
|
||||
for (byte_off = 0; byte_off < bytes_read; byte_off++) {
|
||||
if ((byte_off % 16) == 0)
|
||||
printf("\n%.2X: ", byte_off);
|
||||
printf(" %.2x ", (uint8_t)buf[byte_off]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (!sleep_time)
|
||||
return;
|
||||
|
||||
printf("\n");
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
sleep(sleep_time);
|
||||
|
||||
bytes_read = read(fd, buf2, EC_SPACE_SIZE);
|
||||
|
||||
if (bytes_read == -1)
|
||||
err(EXIT_FAILURE, "Could not read from %s\n", SYSFS_PATH);
|
||||
|
||||
if (bytes_read != EC_SPACE_SIZE)
|
||||
fprintf(stderr, "Could only read %d bytes\n", bytes_read);
|
||||
|
||||
printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
|
||||
for (byte_off = 0; byte_off < bytes_read; byte_off++) {
|
||||
if ((byte_off % 16) == 0)
|
||||
printf("\n%.2X: ", byte_off);
|
||||
|
||||
if (buf[byte_off] == buf2[byte_off])
|
||||
printf(" %.2x ", (uint8_t)buf2[byte_off]);
|
||||
else
|
||||
printf("*%.2x ", (uint8_t)buf2[byte_off]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void read_ec_val(int fd, int byte_offset)
|
||||
{
|
||||
uint8_t buf;
|
||||
int error;
|
||||
|
||||
error = lseek(fd, byte_offset, SEEK_SET);
|
||||
if (error != byte_offset)
|
||||
err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset);
|
||||
|
||||
error = read(fd, &buf, 1);
|
||||
if (error != 1)
|
||||
err(EXIT_FAILURE, "Could not read byte 0x%.2x from %s\n",
|
||||
byte_offset, SYSFS_PATH);
|
||||
printf("0x%.2x\n", buf);
|
||||
return;
|
||||
}
|
||||
|
||||
void write_ec_val(int fd, int byte_offset, uint8_t value)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = lseek(fd, byte_offset, SEEK_SET);
|
||||
if (error != byte_offset)
|
||||
err(EXIT_FAILURE, "Cannot set offset to 0x%.2x", byte_offset);
|
||||
|
||||
error = write(fd, &value, 1);
|
||||
if (error != 1)
|
||||
err(EXIT_FAILURE, "Cannot write value 0x%.2x to offset 0x%.2x",
|
||||
value, byte_offset);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int file_mode = O_RDONLY;
|
||||
int fd;
|
||||
|
||||
parse_opts(argc, argv);
|
||||
|
||||
if (read_mode == 0)
|
||||
file_mode = O_WRONLY;
|
||||
else if (read_mode == 1)
|
||||
file_mode = O_RDONLY;
|
||||
else
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
|
||||
fd = open(SYSFS_PATH, file_mode);
|
||||
if (fd == -1)
|
||||
err(EXIT_FAILURE, "%s", SYSFS_PATH);
|
||||
|
||||
if (read_mode)
|
||||
if (read_byte_offset == -1)
|
||||
dump_ec(fd);
|
||||
else if (read_byte_offset < 0 ||
|
||||
read_byte_offset >= EC_SPACE_SIZE)
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
else
|
||||
read_ec_val(fd, read_byte_offset);
|
||||
else
|
||||
write_ec_val(fd, write_byte_offset, write_value);
|
||||
close(fd);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
Reference in New Issue
Block a user