summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2005-10-26 12:48:02 +1000
committerEric W. Biederman <ebiederm@xmission.com>2006-07-27 09:54:05 -0600
commit7c4a2dc90f22ef8b821aa6a1f3d551facec47a48 (patch)
tree9cfb43de905db439a42347b9ae2bf4890378800e
parent72df5597c20e9a02776b987226828f33141414c9 (diff)
kexec tools: devicetreeblob option
This adds the device tree blob option to kexec. This option is useful if you want to generate you own device tree blobs. Also, you can now do something like: dtc -I fs /proc/device-tree -O dts -f > dt.dts <insert some massaging[1] of dt.dts> dtc -I dts dt.dts -O dtb -f > dt.dtb kexec -l vmlinux --devicetreeblob=dt.dtb taskset 1 kexec -e And get a similar results to just running kexec normally. Also, the --devicetreeblob option won't work with the --initrd option. 1. massaging includes (from memory) - removal of htab entries - ensure CPU are ordered from 0 onwards - adding of reserve map entries (need to create fake last entry for the blob which kexec will patch after loading) Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Maneesh Soni <maneesh@in.ibm.com>
-rw-r--r--kexec/arch/ppc64/kexec-elf-ppc64.c30
-rw-r--r--kexec/arch/ppc64/kexec-ppc64.c1
2 files changed, 30 insertions, 1 deletions
diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index f7fbeae..4423636 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -73,16 +73,19 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
const char *input_options;
int command_line_len;
const char *ramdisk;
+ const char *devicetreeblob;
unsigned long *lp;
int result;
int opt;
#define OPT_APPEND (OPT_ARCH_MAX+0)
#define OPT_RAMDISK (OPT_ARCH_MAX+1)
+#define OPT_DEVICETREEBLOB (OPT_ARCH_MAX+2)
static const struct option options[] = {
KEXEC_ARCH_OPTIONS
{ "append", 1, NULL, OPT_APPEND },
{ "ramdisk", 1, NULL, OPT_RAMDISK },
+ { "devicetreeblob", 1, NULL, OPT_DEVICETREEBLOB },
{ 0, 0, NULL, 0 },
};
@@ -94,6 +97,7 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
command_line = 0;
input_options = 0;
ramdisk = 0;
+ devicetreeblob = 0;
while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
switch (opt) {
@@ -111,6 +115,9 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
case OPT_RAMDISK:
ramdisk = optarg;
break;
+ case OPT_DEVICETREEBLOB:
+ devicetreeblob = optarg;
+ break;
}
}
@@ -156,6 +163,10 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
/* Add a ram-disk to the current image */
if (ramdisk) {
+ if (devicetreeblob) {
+ fprintf(stderr, "Can't use ramdisk with device tree blob input\n");
+ return -1;
+ }
unsigned char *ramdisk_buf = NULL;
off_t ramdisk_size = 0;
unsigned long long ramdisk_addr;
@@ -182,7 +193,24 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
}
memcpy(v2wrap_buf, purgatory, purgatory_size);
v2wrap_size = purgatory_size;
- create_flatten_tree(info, &v2wrap_buf, &v2wrap_size);
+ if (devicetreeblob) {
+ unsigned char *blob_buf = NULL;
+ off_t blob_size = 0;
+ unsigned char *tmp_buf = NULL;
+
+ /* Grab device tree from buffer */
+ blob_buf = slurp_file(devicetreeblob, &blob_size);
+
+ /* Append to purgatory */
+ tmp_buf = (unsigned char *) realloc(v2wrap_buf, v2wrap_size + blob_size);
+ v2wrap_buf = tmp_buf;
+ memcpy(v2wrap_buf+v2wrap_size, blob_buf, blob_size);
+ v2wrap_size += blob_size;
+
+ } else {
+ /* create from fs2dt */
+ create_flatten_tree(info, &v2wrap_buf, &v2wrap_size);
+ }
add_buffer(info, v2wrap_buf, v2wrap_size, v2wrap_size, 0, 0,
0xFFFFFFFFFFFFFFFFUL, -1);
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index 536bab3..11138b7 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -468,6 +468,7 @@ int file_types = sizeof(file_type) / sizeof(file_type[0]);
void arch_usage(void)
{
+ fprintf(stderr, " --devicetreeblob=<filename> Specify device tree blob file.\n");
}
static struct {