Hi,
This is version 2 of the patch
Changes from Version 1 :
: Changed the interface for read_memory_region_limits to use 'int fd'
instead of FILE*.
: Use sizeof(variable) for read(, instead of sizeof(type).
---
Fix parsing of the memory region information from the device-tree.
The format of memory/reg is based on the #address-cells,#size-cells. Currently,
the kexec-tools doesn't use the above values in parsing the memory/reg values.
Hence the kexec cannot handle cases where #address-cells, #size-cells are
different, (for e.g, PPC440X ).
This patch introduces a read_memory_region_limits(), which parses the
memory/reg contents based on the values of #address-cells and #size-cells.
Signed-off-by: Suzuki K. Poulose
---
kexec/arch/ppc/crashdump-powerpc.c | 33 +--
kexec/arch/ppc/fs2dt.c | 14 ---
kexec/arch/ppc/kexec-ppc.c | 158 ++---
kexec/arch/ppc/kexec-ppc.h |6 +
4 files changed, 129 insertions(+), 82 deletions(-)
Index: kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.c
===
--- kexec-tools-2.0.4.orig/kexec/arch/ppc/kexec-ppc.c
+++ kexec-tools-2.0.4/kexec/arch/ppc/kexec-ppc.c
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
#include
#include "../../kexec.h"
@@ -26,6 +27,7 @@
#include "config.h"
+unsigned long dt_address_cells = 0, dt_size_cells = 0;
uint64_t rmo_top;
unsigned long long crash_base = 0, crash_size = 0;
unsigned long long initrd_base = 0, initrd_size = 0;
@@ -34,6 +36,98 @@ unsigned int rtas_base, rtas_size;
int max_memory_ranges;
const char *ramdisk;
+/*
+ * Reads the #address-cells and #size-cells on this platform.
+ * This is used to parse the memory/reg info from the device-tree
+ */
+int init_memory_region_info()
+{
+ size_t res = 0;
+ int fd;
+ char *file;
+
+ file = "/proc/device-tree/#address-cells";
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Unable to open %s\n", file);
+ return -1;
+ }
+
+ res = read(fd, &dt_address_cells, sizeof(dt_address_cells));
+ if (res != sizeof(dt_address_cells)) {
+ fprintf(stderr, "Error reading %s\n", file);
+ return -1;
+ }
+ close(fd);
+
+ file = "/proc/device-tree/#size-cells";
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Unable to open %s\n", file);
+ return -1;
+ }
+
+ res = read(fd, &dt_size_cells, sizeof(dt_size_cells));
+ if (res != sizeof(dt_size_cells)) {
+ fprintf(stderr, "Error reading %s\n", file);
+ return -1;
+ }
+ close(fd);
+
+ /* Convert the sizes into bytes */
+ dt_size_cells *= sizeof(unsigned long);
+ dt_address_cells *= sizeof(unsigned long);
+
+ return 0;
+}
+
+#define MAXBYTES 128
+/*
+ * Reads the memory region info from the device-tree node pointed
+ * by @fd and fills the *start, *end with the boundaries of the region
+ */
+int read_memory_region_limits(int fd, unsigned long long *start,
+ unsigned long long *end)
+{
+ char buf[MAXBYTES];
+ unsigned long *p;
+ unsigned long nbytes = dt_address_cells + dt_size_cells;
+
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ fprintf(stderr, "Error in file seek\n");
+ return -1;
+ }
+ if (read(fd, buf, nbytes) != nbytes) {
+ fprintf(stderr, "Error reading the memory region info\n");
+ return -1;
+ }
+
+ p = (unsigned long*)buf;
+ if (dt_address_cells == sizeof(unsigned long)) {
+ *start = p[0];
+ p++;
+ } else if (dt_address_cells == sizeof(unsigned long long)) {
+ *start = ((unsigned long long *)p)[0];
+ p = (unsigned long long *)p + 1;
+ } else {
+ fprintf(stderr, "Unsupported value for #address-cells : %ld\n",
+ dt_address_cells);
+ return -1;
+ }
+
+ if (dt_size_cells == sizeof(unsigned long))
+ *end = *start + p[0];
+ else if (dt_size_cells == sizeof(unsigned long long))
+ *end = *start + ((unsigned long long *)p)[0];
+ else {
+ fprintf(stderr, "Unsupported value for #size-cells : %ld\n",
+ dt_size_cells);
+ return -1;
+ }
+
+ return 0;
+}
+
void arch_reuse_initrd(void)
{
reuse_initrd = 1;
@@ -182,9 +276,6 @@ static int sort_base_ranges(void)
return 0;
}
-
-#define MAXBYTES 128
-
static int realloc_memory_ranges(void)
{
size_t memory_range_len;
@@ -228,9 +319,8 @@ static int get_base_ranges(void)
char fname[256];
char buf[MAXBYTES];
DIR *dir, *dmem;
- FILE *file;