From 31530cc388ab64805ee39bf184a323ce40b6d802 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@ncos.nec.co.jp>
Date: Mon, 17 Jan 2011 15:31:52 +0900
Subject: [PATCH 1/3] new ikconfig API.

IKCFG_SETUP/IKCFG_FREE args are added into read_in_kernel_config().

get_kernel_config() is new API which can get active kernel config
after read_in_kernel_config(IKCFG_SETUP).
Must be CONFIG_IKCONFIG=y for target kernel.

Maybe this API is also useful for extension users who write kernel config
depended code.

crash> extend dll
-> read_in_kernel_config(IKCFG_SETUP) from constructor.

       get_kernel_config() can work if CONFIG_IKCONFIG=y.

crash> extend -u dll
-> read_in_kernel_config(IKCFG_FREE) from destructor.

Signed-off-by: Toshikazu Nakayama <nakayama.ts@ncos.nec.co.jp>
---
 crash-5.1.1/defs.h   |   13 +++++
 crash-5.1.1/kernel.c |  124 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 137 insertions(+), 0 deletions(-)

diff --git a/crash-5.1.1/defs.h b/crash-5.1.1/defs.h
index 22f876b..1f83094 100755
--- a/crash-5.1.1/defs.h
+++ b/crash-5.1.1/defs.h
@@ -577,6 +577,9 @@ struct kernel_table {                   /* kernel data */
 		ulong p2m_missing;
 	} pvops_xen;
 	int highest_irq;
+	int ikconfig_setup;
+	int ikconfig_ents;
+	int ikconfig_refs;
 };
 
 /*
@@ -4052,6 +4055,16 @@ void read_in_kernel_config(int);
 
 #define IKCFG_INIT   (0)
 #define IKCFG_READ   (1)
+#define IKCFG_SETUP  (2)
+#define IKCFG_FREE   (3)
+
+int get_kernel_config(char *, char **);
+enum {
+	IKCONFIG_N,
+	IKCONFIG_Y,
+	IKCONFIG_M,
+	IKCONFIG_STR,
+};
 
 #define MAGIC_START  "IKCFG_ST"
 #define MAGIC_END    "IKCFG_ED"
diff --git a/crash-5.1.1/kernel.c b/crash-5.1.1/kernel.c
index 21236d0..c9beb4a 100755
--- a/crash-5.1.1/kernel.c
+++ b/crash-5.1.1/kernel.c
@@ -6818,7 +6818,109 @@ search_mapping_page(ulong mfn, ulong *index, ulong *startptr, ulong *endptr)
 	return found;
 }
 
+/*
+ * IKCONFIG management.
+ */
+#define IKCONFIG_MAX		5000
+static struct ikconfig_list {
+	char *name;
+	char *val;
+} *ikconfig_all;
+
+static void add_ikconfig_entry(char *line, struct ikconfig_list *ent)
+{
+	char *tokptr, *name, *val;
+
+	name = strtok_r(line, "=", &tokptr);
+	sscanf(name, "CONFIG_%s", name);
+	val = strtok_r(NULL, "", &tokptr);
+
+	ent->name = strdup(name);
+	ent->val = strdup(val);
+}
+
+static int setup_ikconfig(char *config)
+{
+	char *ent, *tokptr;
+
+	ikconfig_all = calloc(1, sizeof(struct ikconfig_list) * IKCONFIG_MAX);
+	if (!ikconfig_all) {
+		error(WARNING, "cannot calloc for ikconfig entries.\n");
+		return 0;
+	}
 
+	ent =  strtok_r(config, "\n", &tokptr);
+	while (ent) {
+		while (whitespace(*ent))
+			ent++;
+
+		if (ent[0] != '#') {
+			add_ikconfig_entry(ent,
+					 &ikconfig_all[kt->ikconfig_ents++]);
+			if (kt->ikconfig_ents == IKCONFIG_MAX) {
+				error(WARNING, "ikconfig overflow.\n");
+				return 1;
+			}
+		}
+		ent = strtok_r(NULL, "\n", &tokptr);
+	}
+	if (kt->ikconfig_ents == 0) {
+		free(ikconfig_all);
+		return 0;
+	}
+	ikconfig_all = realloc(ikconfig_all,
+			   sizeof(struct ikconfig_list) * kt->ikconfig_ents);
+
+	return 1;
+}
+
+static void free_ikconfig(void)
+{
+	int i;
+
+	for (i = 0; i < kt->ikconfig_ents; i++) {
+		free(ikconfig_all[i].name);
+		free(ikconfig_all[i].val);
+	}
+	free(ikconfig_all);
+}
+
+int get_kernel_config(char *conf_name, char **str)
+{
+	int i;
+	int ret = IKCONFIG_N;
+	char *name;
+
+	if (!kt->ikconfig_setup) {
+		error(WARNING,
+		      "read_in_kernel_config(IKCFG_SETUP) has not done or\n"
+		      "CONFIG_IKCONFIG is not set\n");
+		return ret;
+	}
+
+	kt->ikconfig_refs++;
+	name = strdup(conf_name);
+	if (!strncmp(name, "CONFIG_", strlen("CONFIG_")))
+		sscanf(name, "CONFIG_%s", name);
+
+	for (i = 0; i < kt->ikconfig_ents; i++) {
+		if (STREQ(name, ikconfig_all[i].name)) {
+			if (str)
+				*str = ikconfig_all[i].val;
+			if (STREQ(ikconfig_all[i].val, "y"))
+				ret = IKCONFIG_Y;
+			else if (STREQ(ikconfig_all[i].val, "m"))
+				ret = IKCONFIG_M;
+			else
+				ret = IKCONFIG_STR;
+
+			break;
+		}
+	}
+	free(name);
+
+	return ret;
+}
 
 /*
  *  Read the relevant IKCONFIG (In Kernel Config) data if available.
@@ -6849,6 +6951,9 @@ read_in_kernel_config(int command)
 		if (command == IKCFG_READ)
 			error(FATAL, 
 			    "kernel_config_data does not exist in this kernel\n");
+		else if (command == IKCFG_SETUP)
+			error(WARNING, 
+			    "kernel_config_data does not exist in this kernel\n");
 		return;
 	}
 	
@@ -6948,6 +7053,25 @@ again:
 
 	pos = uncomp;
 
+	if (command == IKCFG_SETUP) {
+		if (!kt->ikconfig_setup) {
+			kt->ikconfig_setup = setup_ikconfig(pos);
+			if (kt->ikconfig_setup && CRASHDEBUG(1))
+				fprintf(fp,
+					"ikconfig: Setup %d valid configs.\n",
+					kt->ikconfig_ents);
+		} else /* Case of call from multiple extension modules. */
+			kt->ikconfig_setup++;
+		goto out1;
+	} else if (command == IKCFG_FREE) {
+		if (!(--kt->ikconfig_setup)) {
+			free_ikconfig();
+			kt->ikconfig_ents = 0;
+			kt->ikconfig_refs = 0;
+		}
+		goto out1;
+	}
+
 	do {
 		ret = sscanf(pos, "%511[^\n]\n%n", line, &ii);
 		if (ret > 0) {
-- 
1.7.4.rc2.3.g60a2e

