From: Todor Minchev <todor.minchev@linux.intel.com>
To: yocto@yoctoproject.org, meta-intel@yoctoproject.org,
jianxun.zhang@linux.intel.com
Cc: Todor Minchev <todor.minchev@linux.intel.com>
Subject: [PATCH 3/3] rmc: add database extraction functionality
Date: Thu, 2 Feb 2017 14:37:12 -0800 [thread overview]
Message-ID: <20170202223712.8164-4-todor.minchev@linux.intel.com> (raw)
In-Reply-To: <20170202223712.8164-1-todor.minchev@linux.intel.com>
The contents of an existing database file can be extracted in the
current working directory with the -E option. The top level of the
directory tree is rmc_db_dump and all files corresponding to
a given record will be saved in a separate sub-directory. The sub-directory
name of each record is the signature corresponding to the fingerprint for
that record.
Example:
./src/rmc -E -d rmc.db
Successfully extracted rmc.db
Signed-off-by: Todor Minchev <todor.minchev@linux.intel.com>
---
inc/rmc_api.h | 9 ++++++
src/lib/api.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/lib/common/rmcl.c | 3 +-
src/rmc.c | 44 +++++++++++++++++++-------
4 files changed, 126 insertions(+), 15 deletions(-)
diff --git a/inc/rmc_api.h b/inc/rmc_api.h
index a484389..ce26220 100644
--- a/inc/rmc_api.h
+++ b/inc/rmc_api.h
@@ -74,6 +74,15 @@ extern int rmc_query_file_by_fp(rmc_fingerprint_t *fp, char *db_pathname, char *
*/
extern int rmc_gimme_file(char* db_pathname, char *file_name, rmc_file_t *file);
+
+/* extract the contents of a database file and store the files corresponding to
+ * each record in a separate directory. The name of each directory is the signature
+ * of the fingerpring for that record
+ * (in) db_pathname: The path and file name of a RMC database file generated by RMC tool
+ * return: 0 on success, non-zero on failure.
+ */
+int dump_db(char *db_pathname) ;
+
/* 1.3 - Helper APIs */
/* Free allocated data referred in a fingerprint
diff --git a/src/lib/api.c b/src/lib/api.c
index 0adb390..aca8d99 100644
--- a/src/lib/api.c
+++ b/src/lib/api.c
@@ -3,6 +3,7 @@
* RMC API implementation for Linux user space
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
@@ -14,8 +15,11 @@
#include <rmcl.h>
#include <rsmp.h>
-#define EFI_SYSTAB_PATH "/sys/firmware/efi/systab"
-#define SYSTAB_LEN 4096 /* assume 4kb is enough...*/
+#define EFI_SYSTAB_PATH "/sys/firmware/efi/systab"
+#define SYSTAB_LEN 4096 /* assume 4kb is enough...*/
+#define DB_DUMP_DIR "./rmc_db_dump" /* directory to store db data dump */
+
+extern const rmc_uint8_t rmc_db_signature[RMC_DB_SIG_LEN];
int read_file(const char *pathname, char **data, rmc_size_t* len) {
int fd = -1;
@@ -325,3 +329,80 @@ int rmc_gimme_file(char* db_pathname, char *file_name, rmc_file_t *file) {
return ret;
}
+
+/*
+ * Dump contents of database file
+ * (in) rmc_db - input database file to extract
+ */
+int dump_db(char *db_pathname) {
+ rmc_meta_header_t meta_header;
+ rmc_db_header_t *db_header = NULL;
+ rmc_record_header_t record_header;
+ rmc_uint64_t record_idx = 0; /* offset of each reacord in db*/
+ rmc_uint64_t meta_idx = 0; /* offset of each meta in a record */
+ rmc_uint64_t file_idx = 0; /* offset of file in a meta */
+ rmc_file_t file;
+ char *out_dir = NULL, *out_name = NULL;
+ rmc_size_t db_len = 0;
+ rmc_uint8_t *rmc_db = NULL;
+ struct stat s = {0};
+
+ if (read_file(db_pathname, (char **)&rmc_db, &db_len)) {
+ fprintf(stderr, "Failed to read database file\n\n");
+ return 1;
+ }
+
+ db_header = (rmc_db_header_t *)rmc_db;
+
+ /* sanity check of db */
+ if (strncmp((const char *)db_header->signature,
+ (const char *)rmc_db_signature, RMC_DB_SIG_LEN))
+ return 1;
+
+ /* create the top level directory */
+ if (stat(DB_DUMP_DIR, &s) == -1) {
+ if(mkdir(DB_DUMP_DIR, 0755)) {
+ fprintf(stderr, "Failed to create %s directory\n\n", out_name);
+ }
+ }
+
+ /* query the meta. idx: start of record */
+ record_idx = sizeof(rmc_db_header_t);
+ while (record_idx < db_header->length) {
+ memcpy(&record_header, rmc_db + record_idx,
+ sizeof(rmc_record_header_t));
+
+ /* directory name is fingerprint signature */
+ asprintf(&out_dir, "%s/%s/", DB_DUMP_DIR, record_header.signature.raw);
+ if (stat(out_dir, &s) == -1) {
+ if(mkdir(out_dir, 0755)) {
+ fprintf(stderr, "Failed to create %s directory\n\n", out_name);
+ }
+ }
+
+ /* find meta */
+ for (meta_idx = record_idx + sizeof(rmc_record_header_t);
+ meta_idx < record_idx + record_header.length;) {
+ memcpy(&meta_header, rmc_db + meta_idx, sizeof(rmc_meta_header_t));
+ file_idx = meta_idx + sizeof(rmc_meta_header_t);
+ rmc_ssize_t name_len = strlen((char *)&rmc_db[file_idx]) + 1;
+ file.blob = &rmc_db[file_idx + name_len];
+ file.blob_len = meta_header.length - sizeof(rmc_meta_header_t) -
+ name_len;
+ file.next = NULL;
+ file.type = RMC_GENERIC_FILE;
+ asprintf(&out_name, "%s%s", out_dir, (char *)&rmc_db[file_idx]);
+ /* write file to dump directory */
+ if (write_file((const char *)out_name, file.blob, file.blob_len, 0))
+ return 1;
+
+ /* next meta */
+ meta_idx += meta_header.length;
+ free(out_name);
+ }
+ /* next record */
+ record_idx += record_header.length;
+ free(out_dir);
+ }
+ return 0;
+}
diff --git a/src/lib/common/rmcl.c b/src/lib/common/rmcl.c
index 67622a0..c996577 100644
--- a/src/lib/common/rmcl.c
+++ b/src/lib/common/rmcl.c
@@ -10,7 +10,7 @@
#include <rmc_util.h>
#endif
-static const rmc_uint8_t rmc_db_signature[RMC_DB_SIG_LEN] = {'R', 'M', 'C', 'D', 'B'};
+const rmc_uint8_t rmc_db_signature[RMC_DB_SIG_LEN] = {'R', 'M', 'C', 'D', 'B'};
/* compute a finger to signature which is stored in record
* (in) fingerprint : of board, usually generated by rmc tool and rsmp
@@ -242,7 +242,6 @@ int query_policy_from_db(rmc_fingerprint_t *fingerprint, rmc_uint8_t *rmc_db, rm
policy->blob_len = meta_header.length - sizeof(rmc_meta_header_t) - cmd_name_len;
policy->next = NULL;
policy->type = type;
-
return 0;
}
}
diff --git a/src/rmc.c b/src/rmc.c
index a051ccf..888cbdb 100644
--- a/src/rmc.c
+++ b/src/rmc.c
@@ -32,6 +32,8 @@
"running on\n" \
"\t-d: database file to be queried\n" \
"\t-o: path and name of output file of a specific command\n\n" \
+ "-E: Extract database data to current working directory\n" \
+ "\t-d: database file to extract\n\n" \
"Examples (Steps in an order to add board support into rmc):\n\n" \
"1. Generate board fingerprint:\n" \
"\t./rmc -F\n\n" \
@@ -49,11 +51,12 @@
#define RMC_OPT_CAP_R (1 << 1)
#define RMC_OPT_CAP_D (1 << 2)
#define RMC_OPT_CAP_B (1 << 3)
-#define RMC_OPT_F (1 << 4)
-#define RMC_OPT_O (1 << 5)
-#define RMC_OPT_B (1 << 6)
-#define RMC_OPT_D (1 << 7)
-#define RMC_OPT_I (1 << 8)
+#define RMC_OPT_CAP_E (1 << 4)
+#define RMC_OPT_F (1 << 5)
+#define RMC_OPT_O (1 << 6)
+#define RMC_OPT_B (1 << 7)
+#define RMC_OPT_D (1 << 8)
+#define RMC_OPT_I (1 << 9)
static void usage () {
fprintf(stdout, USAGE);
@@ -312,7 +315,7 @@ int main(int argc, char **argv){
/* parse options */
opterr = 0;
- while ((c = getopt(argc, argv, "FRD:B:b:f:o:i:d:")) != -1)
+ while ((c = getopt(argc, argv, "FRED:B:b:f:o:i:d:")) != -1)
switch (c) {
case 'F':
options |= RMC_OPT_CAP_F;
@@ -320,6 +323,9 @@ int main(int argc, char **argv){
case 'R':
options |= RMC_OPT_CAP_R;
break;
+ case 'E':
+ options |= RMC_OPT_CAP_E;
+ break;
case 'D':
/* we don't know number of arguments for this option at this point,
* allocate array with argc which is bigger than needed. But we also
@@ -393,8 +399,8 @@ int main(int argc, char **argv){
break;
case '?':
if (optopt == 'F' || optopt == 'R' || optopt == 'D' || optopt == 'B' || \
- optopt == 'b' || optopt == 'f' || optopt == 'o' || optopt == 'd' \
- || optopt == 'i')
+ optopt == 'E' || optopt == 'b' || optopt == 'f' || \
+ optopt == 'o' || optopt == 'd' || optopt == 'i')
fprintf(stderr, "\nWRONG USAGE: -%c\n\n", optopt);
else if (isprint(optopt))
fprintf(stderr, "Unknown option `-%c'.\n\n", optopt);
@@ -436,6 +442,13 @@ int main(int argc, char **argv){
return 1;
}
+ /* sanity check for -E */
+ if ((options & RMC_OPT_CAP_E) && (!(options & RMC_OPT_D))) {
+ fprintf(stderr, "\nERROR: -E requires -d <database file name>\n\n");
+ usage();
+ return 1;
+ }
+
/* sanity check for -B */
if ((options & RMC_OPT_CAP_B) && (!(options & RMC_OPT_D) || !(options & RMC_OPT_O))) {
fprintf(stderr, "\nWRONG: -B requires -d and -o\n\n");
@@ -448,7 +461,8 @@ int main(int argc, char **argv){
rmc_file_t file;
if (!output_path) {
- fprintf(stderr, "-B internal error, with -o but no output pathname specified\n\n");
+ fprintf(stderr, "-B internal error, with -o but no output \
+ pathname specified\n\n");
goto main_free;
}
@@ -456,14 +470,22 @@ int main(int argc, char **argv){
goto main_free;
if (write_file(output_path, file.blob, file.blob_len, 0)) {
- fprintf(stderr, "-B failed to write file %s to %s\n\n", input_blob_name, output_path);
+ fprintf(stderr, "-B failed to write file %s to %s\n\n",
+ input_blob_name, output_path);
rmc_free_file(&file);
goto main_free;
}
-
rmc_free_file(&file);
}
+ /* dump database data */
+ if (options & RMC_OPT_CAP_E) {
+ if(dump_db(input_db_path_d))
+ fprintf(stderr, "\nFailed to extract %s\n\n", input_db_path_d);
+ else
+ printf("\nSuccessfully extracted %s\n\n", input_db_path_d);
+ }
+
/* generate RMC database file */
if (options & RMC_OPT_CAP_D) {
int record_idx = 0;
--
2.11.0
next prev parent reply other threads:[~2017-02-02 22:37 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-02 22:37 [PATCH 0/3] [meta-intel][rmc] Add fingerprint quering and database extraction functionality to RMC Todor Minchev
2017-02-02 22:37 ` [PATCH 1/3] Makefile: add verbosity and debug options to Makefile Todor Minchev
2017-02-06 19:06 ` Jianxun Zhang
2017-02-06 22:21 ` Todor Minchev
2017-02-02 22:37 ` [PATCH 2/3] rmc: Enable reading the contents of an existing fingerprint file Todor Minchev
2017-02-06 20:01 ` Jianxun Zhang
2017-02-06 22:28 ` Todor Minchev
2017-02-06 23:12 ` Jianxun Zhang
2017-02-02 22:37 ` Todor Minchev [this message]
2017-02-06 21:09 ` [PATCH 3/3] rmc: add database extraction functionality Jianxun Zhang
2017-02-06 23:09 ` Todor Minchev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170202223712.8164-4-todor.minchev@linux.intel.com \
--to=todor.minchev@linux.intel.com \
--cc=jianxun.zhang@linux.intel.com \
--cc=meta-intel@yoctoproject.org \
--cc=yocto@yoctoproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.