On some actitectures the physical memory can be 64 bits, therefore the code that reads proc entries needs to take into account it could read either a 32 bit or 64bit value for the physical addresses. Signed-off-by: Matthew McClintock <msm at freescale.com> --- kexec/arch/ppc/kexec-elf-ppc.c | 1 - kexec/arch/ppc/kexec-ppc.c | 198 +++++++++++++++++++++++----------------- 2 files changed, 114 insertions(+), 85 deletions(-) diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c index d155bde..ab2d343 100644 --- a/kexec/arch/ppc/kexec-elf-ppc.c +++ b/kexec/arch/ppc/kexec-elf-ppc.c @@ -32,7 +32,6 @@ static const int probe_debug = 0; -unsigned long long initrd_base, initrd_size; unsigned char reuse_initrd; const char *ramdisk; int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *, diff --git a/kexec/arch/ppc/kexec-ppc.c b/kexec/arch/ppc/kexec-ppc.c index ca33303..e1547a8 100644 --- a/kexec/arch/ppc/kexec-ppc.c +++ b/kexec/arch/ppc/kexec-ppc.c @@ -28,6 +28,7 @@ uint64_t rmo_top; unsigned long long crash_base, crash_size; +unsigned long long initrd_base, initrd_size; unsigned int rtas_base, rtas_size; int max_memory_ranges; @@ -262,14 +263,14 @@ static int get_base_ranges(void) } } - if (n == 8) { + if (n == sizeof(uint32_t) * 2) { base_memory_range[local_memory_ranges].start = ((uint32_t *)buf)[0]; base_memory_range[local_memory_ranges].end = base_memory_range[local_memory_ranges].start + ((uint32_t *)buf)[1]; } - else if (n == 16) { + else if (n == sizeof(uint64_t) * 2) { base_memory_range[local_memory_ranges].start = ((uint64_t *)buf)[0]; base_memory_range[local_memory_ranges].end = @@ -317,9 +318,7 @@ static int get_devtree_details(unsigned long kexec_flags) DIR *dir, *cdir; FILE *file; struct dirent *dentry; - struct stat fstat; int n, i = 0; - unsigned long tmp_long; if ((dir = opendir(device_tree)) == NULL) { perror(device_tree); @@ -349,12 +348,18 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_opencdir; } - if (fread(&tmp_long, sizeof(unsigned long), 1, file) - != 1) { + if ((n = fread(buf, 1, MAXBYTES, file)) < 0) { perror(fname); goto error_openfile; } - kernel_end = tmp_long; + if (n == sizeof(uint32_t)) { + kernel_end = ((uint32_t *)buf)[0]; + } else if (n == sizeof(uint64_t)) { + kernel_end = ((uint64_t *)buf)[0]; + } else { + fprintf(stderr, "%s node has invalid size: %d\n", fname, n); + goto error_openfile; + } fclose(file); /* Add kernel memory to exclude_range */ @@ -364,37 +369,50 @@ static int get_devtree_details(unsigned long kexec_flags) if (i >= max_memory_ranges) realloc_memory_ranges(); memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/linux,crashkernel-base"); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,crashkernel-base"); file = fopen(fname, "r"); if (!file) { perror(fname); goto error_opencdir; } - if (fread(&tmp_long, sizeof(unsigned long), 1, - file) != 1) { + if ((n = fread(buf, 1, MAXBYTES, file)) < 0) { perror(fname); goto error_openfile; } - crash_base = tmp_long; + if (n == sizeof(uint32_t)) { + crash_base = ((uint32_t *)buf)[0]; + } else if (n == sizeof(uint64_t)) { + crash_base = ((uint64_t *)buf)[0]; + } else { + fprintf(stderr, "%s node has invalid size: %d\n", fname, n); + goto error_openfile; + } fclose(file); memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/linux,crashkernel-size"); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,crashkernel-size"); file = fopen(fname, "r"); if (!file) { perror(fname); goto error_opencdir; } - if (fread(&tmp_long, sizeof(unsigned long), 1, - file) != 1) { + if ((n = fread(buf, 1, MAXBYTES, file)) < 0) { perror(fname); goto error_openfile; } - crash_size = tmp_long; + if (n == sizeof(uint32_t)) { + crash_size = ((uint32_t *)buf)[0]; + } else if (n == sizeof(uint64_t)) { + crash_size = ((uint64_t *)buf)[0]; + } else { + fprintf(stderr, "%s node has invalid size: %d\n", fname, n); + goto error_openfile; + } + fclose(file); if (crash_base > mem_min) mem_min = crash_base; @@ -405,10 +423,74 @@ static int get_devtree_details(unsigned long kexec_flags) reserve(KDUMP_BACKUP_LIMIT, crash_base-KDUMP_BACKUP_LIMIT); } + /* reserve the initrd_start and end locations. */ memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/linux,htab-base"); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,initrd-start"); + file = fopen(fname, "r"); + if (!file) { + errno = 0; + initrd_start = 0; + } else { + if ((n = fread(buf, 1, MAXBYTES, file)) < 0) { + perror(fname); + goto error_openfile; + } + if (n == sizeof(uint32_t)) { + initrd_start = ((uint32_t *)buf)[0]; + } else if (n == sizeof(uint64_t)) { + initrd_start = ((uint64_t *)buf)[0]; + } else { + fprintf(stderr, "%s node has invalid size: %d\n", fname, n); + goto error_openfile; + } + fclose(file); + } + + memset(fname, 0, sizeof(fname)); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,initrd-end"); + file = fopen(fname, "r"); + if (!file) { + errno = 0; + initrd_end = 0; + } else { + if ((n = fread(buf, 1, MAXBYTES, file)) < 0) { + perror(fname); + goto error_openfile; + } + if (n == sizeof(uint32_t)) { + initrd_end = ((uint32_t *)buf)[0]; + } else if (n == sizeof(uint64_t)) { + initrd_end = ((uint64_t *)buf)[0]; + } else { + fprintf(stderr, "%s node has invalid size: %d\n", fname, n); + goto error_openfile; + } + fclose(file); + } + + if ((initrd_end - initrd_start) != 0 ) { + initrd_base = initrd_start; + initrd_size = initrd_end - initrd_start + 1; + } + + if (reuse_initrd) { + /* Add initrd address to exclude_range */ + exclude_range[i].start = initrd_start; + exclude_range[i].end = initrd_end; + i++; + if (i >= max_memory_ranges) + realloc_memory_ranges(); + } + + /* HTAB */ + memset(fname, 0, sizeof(fname)); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,htab-base"); file = fopen(fname, "r"); if (!file) { closedir(cdir); @@ -426,9 +508,9 @@ static int get_devtree_details(unsigned long kexec_flags) goto error_openfile; } memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/linux,htab-size"); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,htab-size"); file = fopen(fname, "r"); if (!file) { perror(fname); @@ -446,59 +528,7 @@ static int get_devtree_details(unsigned long kexec_flags) if (i >= max_memory_ranges) realloc_memory_ranges(); - /* reserve the initrd_start and end locations. */ - if (reuse_initrd) { - memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/linux,initrd-start"); - file = fopen(fname, "r"); - if (!file) { - perror(fname); - goto error_opencdir; - } - /* check for 4 and 8 byte initrd offset sizes */ - if (stat(fname, &fstat) != 0) { - perror(fname); - goto error_openfile; - } - if (fread(&initrd_start, fstat.st_size, 1, file) - != 1) { - perror(fname); - goto error_openfile; - } - fclose(file); - - memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/linux,initrd-end"); - file = fopen(fname, "r"); - if (!file) { - perror(fname); - goto error_opencdir; - } - /* check for 4 and 8 byte initrd offset sizes */ - if (stat(fname, &fstat) != 0) { - perror(fname); - goto error_openfile; - } - if (fread(&initrd_end, fstat.st_size, 1, file) - != 1) { - perror(fname); - goto error_openfile; - } - fclose(file); - - /* Add initrd address to exclude_range */ - exclude_range[i].start = initrd_start; - exclude_range[i].end = initrd_end; - i++; - if (i >= max_memory_ranges) - realloc_memory_ranges(); - } } /* chosen */ - if (strncmp(dentry->d_name, "rtas", 4) == 0) { strcat(fname, "/linux,rtas-base"); if ((file = fopen(fname, "r")) == NULL) { @@ -511,9 +541,9 @@ static int get_devtree_details(unsigned long kexec_flags) goto error_openfile; } memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/rtas-size"); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,rtas-size"); if ((file = fopen(fname, "r")) == NULL) { perror(fname); goto error_opencdir; @@ -543,7 +573,7 @@ static int get_devtree_details(unsigned long kexec_flags) perror(fname); goto error_openfile; } - if (n == 8) { + if (n == sizeof(uint64_t)) { rmo_base = ((uint32_t *)buf)[0]; rmo_top = rmo_base + ((uint32_t *)buf)[1]; } else if (n == 16) { @@ -580,9 +610,9 @@ static int get_devtree_details(unsigned long kexec_flags) return -1; } memset(fname, 0, sizeof(fname)); - strcpy(fname, device_tree); - strcat(fname, dentry->d_name); - strcat(fname, "/linux,tce-size"); + sprintf(fname, "%s%s%s", + device_tree, dentry->d_name, + "/linux,tce-size"); file = fopen(fname, "r"); if (!file) { perror(fname); -- 1.6.0.6