Beispiel #1
0
static void add_base_memory_range(uint64_t start, uint64_t end)
{
	base_memory_range[nr_memory_ranges].start = start;
	base_memory_range[nr_memory_ranges].end  = end;
	base_memory_range[nr_memory_ranges].type = RANGE_RAM;
	nr_memory_ranges++;
	if (nr_memory_ranges >= max_memory_ranges)
		realloc_memory_ranges();

	dbgprintf("%016llx-%016llx : %x\n",
		base_memory_range[nr_memory_ranges-1].start,
		base_memory_range[nr_memory_ranges-1].end,
		base_memory_range[nr_memory_ranges-1].type);
}
void scan_reserved_ranges(unsigned long kexec_flags, int *range_index)
{
	char fname[256], buf[16];
	FILE *file;
	int i = *range_index;

	strcpy(fname, "/proc/device-tree/reserved-ranges");

	file = fopen(fname, "r");
	if (file == NULL) {
		if (errno != ENOENT) {
			perror(fname);
			return;
		}
		errno = 0;
		/* File not present. Non PowerKVM system. */
		return;
	}

	/*
	 * Each reserved range is an (address,size) pair, 2 cells each,
	 * totalling 4 cells per range.
	 */
	while (fread(buf, sizeof(uint64_t) * 2, 1, file) == 1) {
		uint64_t base, size;

		base = be64_to_cpu(((uint64_t *)buf)[0]);
		size = be64_to_cpu(((uint64_t *)buf)[1]);

		exclude_range[i].start = base;
		exclude_range[i].end = base + size;
		i++;
		if (i >= max_memory_ranges)
			realloc_memory_ranges();

		reserve(base, size);
	}
	fclose(file);
	*range_index = i;
}
Beispiel #3
0
/* Setup a sorted list of memory ranges. */
int setup_memory_ranges(unsigned long kexec_flags)
{
	int i, j = 0;

	/* Get the base list of memory ranges from /proc/device-tree/memory
	 * nodes. Build list of ranges to be excluded from valid memory
	 */

	if (get_base_ranges())
		goto out;
	if (get_devtree_details(kexec_flags))
		goto out;

	for (i = 0; i < nr_exclude_ranges; i++) {
		/* If first exclude range does not start with 0, include the
		 * first hole of valid memory from 0 - exclude_range[0].start
		 */
		if (i == 0) {
			if (exclude_range[i].start != 0) {
				memory_range[j].start = 0;
				memory_range[j].end = exclude_range[i].start - 1;
				memory_range[j].type = RANGE_RAM;
				j++;
				if (j >= max_memory_ranges)
					realloc_memory_ranges();
			}
		} /* i == 0 */
		/* If the last exclude range does not end at memory_max, include
		 * the last hole of valid memory from exclude_range[last].end -
		 * memory_max
		 */
		if (i == nr_exclude_ranges - 1) {
			if (exclude_range[i].end < memory_max) {
				memory_range[j].start = exclude_range[i].end + 1;
				memory_range[j].end = memory_max;
				memory_range[j].type = RANGE_RAM;
				j++;
				if (j >= max_memory_ranges)
					realloc_memory_ranges();
				/* Limit the end to rmo_top */
				if (memory_range[j-1].start >= rmo_top) {
					j--;
					break;
				}
				if ((memory_range[j-1].start < rmo_top) &&
				(memory_range[j-1].end >= rmo_top)) {
					memory_range[j-1].end = rmo_top;
					break;
				}
				continue;
			}
		} /* i == nr_exclude_ranges - 1 */
		/* contiguous exclude ranges - skip */
		if (exclude_range[i+1].start == exclude_range[i].end + 1)
			continue;
		memory_range[j].start = exclude_range[i].end + 1;
		memory_range[j].end = exclude_range[i+1].start - 1;
		memory_range[j].type = RANGE_RAM;
		j++;
		if (j >= max_memory_ranges)
			realloc_memory_ranges();
		/* Limit range to rmo_top */
		if (memory_range[j-1].start >= rmo_top) {
			j--;
			break;
		}
		if ((memory_range[j-1].start < rmo_top) &&
			(memory_range[j-1].end >= rmo_top)) {
			memory_range[j-1].end = rmo_top;
			break;
		}
	}
	nr_memory_ranges = j;

	int k;
	for (k = 0; k < j; k++)
		dbgprintf("setup_memory_ranges memory_range[%d] "
			"start:%llx, end:%llx\n", k, memory_range[k].start,
			memory_range[k].end);
	return 0;

out:
	cleanup_memory_ranges();
	return -1;
}
Beispiel #4
0
/* Get devtree details and create exclude_range array
 * Also create usablemem_ranges for KEXEC_ON_CRASH
 */
static int get_devtree_details(unsigned long kexec_flags)
{
	uint64_t rmo_base;
	uint64_t tce_base;
	unsigned int tce_size;
	uint64_t htab_base, htab_size;
	uint64_t kernel_end;
	uint64_t initrd_start, initrd_end;
	char buf[MAXBYTES];
	char device_tree[256] = "/proc/device-tree/";
	char fname[256];
	DIR *dir, *cdir;
	FILE *file;
	struct dirent *dentry;
	struct stat fstat;
	int n, i = 0;

	if ((dir = opendir(device_tree)) == NULL) {
		perror(device_tree);
		return -1;
	}

	while ((dentry = readdir(dir)) != NULL) {
		if (strncmp(dentry->d_name, "chosen", 6) &&
			strncmp(dentry->d_name, "memory@", 7) &&
			strcmp(dentry->d_name, "memory") &&
			strncmp(dentry->d_name, "pci@", 4) &&
			strncmp(dentry->d_name, "rtas", 4)) 
			continue;
		strcpy(fname, device_tree);
		strcat(fname, dentry->d_name);
		if ((cdir = opendir(fname)) == NULL) {
			perror(fname);
			goto error_opendir;
		}

		if (strncmp(dentry->d_name, "chosen", 6) == 0) {
			strcat(fname, "/linux,kernel-end");
			if ((file = fopen(fname, "r")) == NULL) {
				perror(fname);
				goto error_opencdir;
			}
			if (fread(&kernel_end, sizeof(uint64_t), 1, file) != 1) {
				perror(fname);
				goto error_openfile;
			}
			fclose(file);
			kernel_end = be64_to_cpu(kernel_end);

			/* Add kernel memory to exclude_range */
			exclude_range[i].start = 0x0UL;
			exclude_range[i].end = kernel_end;
			i++;
			if (i >= max_memory_ranges)
				realloc_memory_ranges();

			if (kexec_flags & KEXEC_ON_CRASH) {
				memset(fname, 0, sizeof(fname));
				strcpy(fname, device_tree);
				strcat(fname, dentry->d_name);
				strcat(fname, "/linux,crashkernel-base");
				if ((file = fopen(fname, "r")) == NULL) {
					perror(fname);
					goto error_opencdir;
				}
				if (fread(&crash_base, sizeof(uint64_t), 1,
						file) != 1) {
					perror(fname);
					goto error_openfile;
				}
				fclose(file);
				crash_base = be64_to_cpu(crash_base);

				memset(fname, 0, sizeof(fname));
				strcpy(fname, device_tree);
				strcat(fname, dentry->d_name);
				strcat(fname, "/linux,crashkernel-size");
				if ((file = fopen(fname, "r")) == NULL) {
					perror(fname);
					goto error_opencdir;
				}
				if (fread(&crash_size, sizeof(uint64_t), 1,
						file) != 1) {
					perror(fname);
					goto error_openfile;
				}
				fclose(file);
				crash_size = be64_to_cpu(crash_size);

				if (crash_base > mem_min)
					mem_min = crash_base;
				if (crash_base + crash_size < mem_max)
					mem_max = crash_base + crash_size;
				
				add_usable_mem_rgns(0, crash_base + crash_size);
				reserve(KDUMP_BACKUP_LIMIT, crash_base-KDUMP_BACKUP_LIMIT);
			}
			/*
			 * Read the first kernel's memory limit.
			 * If the first kernel is booted with mem= option then
			 * it would export "linux,memory-limit" file
			 * reflecting value for the same.
			 */
			memset(fname, 0, sizeof(fname));
			strcpy(fname, device_tree);
			strcat(fname, dentry->d_name);
			strcat(fname, "/linux,memory-limit");
			if ((file = fopen(fname, "r")) == NULL) {
				if (errno != ENOENT) {
					perror(fname);
					goto error_opencdir;
				}
				errno = 0;
				/*
				 * File not present.
				 * fall through. On older kernel this file
				 * is not present.
				 */
			} else {
				if (fread(&memory_limit, sizeof(uint64_t), 1,
					  file) != 1) {
					perror(fname);
					goto error_openfile;
				}
				fclose(file);
				memory_limit = be64_to_cpu(memory_limit);
			}

			memset(fname, 0, sizeof(fname));
			strcpy(fname, device_tree);
			strcat(fname, dentry->d_name);
			strcat(fname, "/linux,htab-base");
			if ((file = fopen(fname, "r")) == NULL) {
				closedir(cdir);
				if (errno == ENOENT) {
					/* Non LPAR */
					errno = 0;
					continue;
                                }
				perror(fname);
				goto error_opendir;
			}
			if (fread(&htab_base, sizeof(uint64_t), 1, file) != 1) {
				perror(fname);
				goto error_openfile;
			}
			fclose(file);
			htab_base = be64_to_cpu(htab_base);

			memset(fname, 0, sizeof(fname));
			strcpy(fname, device_tree);
			strcat(fname, dentry->d_name);
			strcat(fname, "/linux,htab-size");
			if ((file = fopen(fname, "r")) == NULL) {
				perror(fname);
				goto error_opencdir;
			}
			if (fread(&htab_size, sizeof(uint64_t), 1, file) != 1) {
				perror(fname);
				goto error_openfile;
			}
			fclose(file);
			htab_size = be64_to_cpu(htab_size);

			/* Add htab address to exclude_range - NON-LPAR only */
			exclude_range[i].start = htab_base;
			exclude_range[i].end = htab_base + htab_size;
			i++;
			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");
				if ((file = fopen(fname, "r")) == NULL) {
					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;
				}
				initrd_start = be64_to_cpu(initrd_start);
				fclose(file);

				memset(fname, 0, sizeof(fname));
				strcpy(fname, device_tree);
				strcat(fname, dentry->d_name);
				strcat(fname, "/linux,initrd-end");
				if ((file = fopen(fname, "r")) == NULL) {
					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;
				}
				initrd_end = be64_to_cpu(initrd_end);
				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) {
				perror(fname);
				goto error_opencdir;
			}
			if (fread(&rtas_base, sizeof(unsigned int), 1, file) != 1) {
				perror(fname);
				goto error_openfile;
			}
			fclose(file);
			rtas_base = be32_to_cpu(rtas_base);
			memset(fname, 0, sizeof(fname));
			strcpy(fname, device_tree);
			strcat(fname, dentry->d_name);
			strcat(fname, "/rtas-size");
			if ((file = fopen(fname, "r")) == NULL) {
				perror(fname);
				goto error_opencdir;
			}
			if (fread(&rtas_size, sizeof(unsigned int), 1, file) != 1) {
				perror(fname);
				goto error_openfile;
			}
			fclose(file);
			closedir(cdir);
			rtas_size = be32_to_cpu(rtas_size);
			/* Add rtas to exclude_range */
			exclude_range[i].start = rtas_base;
			exclude_range[i].end = rtas_base + rtas_size;
			i++;
			if (i >= max_memory_ranges)
				realloc_memory_ranges();
			if (kexec_flags & KEXEC_ON_CRASH)
				add_usable_mem_rgns(rtas_base, rtas_size);
		} /* rtas */

		if (!strncmp(dentry->d_name, "memory@", 7) ||
			!strcmp(dentry->d_name, "memory")) {
			strcat(fname, "/reg");
			if ((file = fopen(fname, "r")) == NULL) {
				perror(fname);
				goto error_opencdir;
			}
			if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
				perror(fname);
				goto error_openfile;
			}
			rmo_base = be64_to_cpu(((uint64_t *)buf)[0]);
			rmo_top = rmo_base + be64_to_cpu(((uint64_t *)buf)[1]);
			if (rmo_top > 0x30000000UL)
				rmo_top = 0x30000000UL;

			fclose(file);
			closedir(cdir);
		} /* memory */

		if (strncmp(dentry->d_name, "pci@", 4) == 0) {
			strcat(fname, "/linux,tce-base");
			if ((file = fopen(fname, "r")) == NULL) {
				closedir(cdir);
				if (errno == ENOENT) {
					/* Non LPAR */
					errno = 0;
					continue;
				}
				perror(fname);
				goto error_opendir;
			}
			if (fread(&tce_base, sizeof(uint64_t), 1, file) != 1) {
				perror(fname);
				goto error_openfile;
			}
			fclose(file);
			tce_base = be64_to_cpu(tce_base);
			memset(fname, 0, sizeof(fname));
			strcpy(fname, device_tree);
			strcat(fname, dentry->d_name);
			strcat(fname, "/linux,tce-size");
			if ((file = fopen(fname, "r")) == NULL) {
				perror(fname);
				goto error_opencdir;
			}
			if (fread(&tce_size, sizeof(unsigned int), 1, file) != 1) {
				perror(fname);
				goto error_openfile;
			}
			fclose(file);
			tce_size = be32_to_cpu(tce_size);
			/* Add tce to exclude_range - NON-LPAR only */
			exclude_range[i].start = tce_base;
			exclude_range[i].end = tce_base + tce_size;
			i++;
			if (i >= max_memory_ranges)
				realloc_memory_ranges();
			if (kexec_flags & KEXEC_ON_CRASH)
				add_usable_mem_rgns(tce_base, tce_size);
			closedir(cdir);
		} /* pci */
	}
	closedir(dir);

	nr_exclude_ranges = i;

	sort_ranges();

	int k;
	for (k = 0; k < i; k++)
		dbgprintf("exclude_range sorted exclude_range[%d] "
			"start:%llx, end:%llx\n", k, exclude_range[k].start,
			exclude_range[k].end);

	return 0;

error_openfile:
	fclose(file);
error_opencdir:
	closedir(cdir);
error_opendir:
	closedir(dir);
	return -1;
}
Beispiel #5
0
/* Get base memory ranges */
static int get_base_ranges(void)
{
	uint64_t start, end;
	char device_tree[256] = "/proc/device-tree/";
	char fname[256];
	char buf[MAXBYTES];
	DIR *dir, *dmem;
	FILE *file;
	struct dirent *dentry, *mentry;
	int n;

	if ((dir = opendir(device_tree)) == NULL) {
		perror(device_tree);
		return -1;
	}
	while ((dentry = readdir(dir)) != NULL) {
		if (!strncmp(dentry->d_name,
				"ibm,dynamic-reconfiguration-memory", 35)) {
			get_dyn_reconf_base_ranges();
			continue;
		}
		if (strncmp(dentry->d_name, "memory@", 7) &&
			strcmp(dentry->d_name, "memory"))
			continue;
		strcpy(fname, device_tree);
		strcat(fname, dentry->d_name);
		if ((dmem = opendir(fname)) == NULL) {
			perror(fname);
			closedir(dir);
			return -1;
		}
		while ((mentry = readdir(dmem)) != NULL) {
			if (strcmp(mentry->d_name, "reg"))
				continue;
			strcat(fname, "/reg");
			if ((file = fopen(fname, "r")) == NULL) {
				perror(fname);
				closedir(dmem);
				closedir(dir);
				return -1;
			}
			if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
				perror(fname);
				fclose(file);
				closedir(dmem);
				closedir(dir);
				return -1;
			}
			if (nr_memory_ranges >= max_memory_ranges) {
				if (realloc_memory_ranges() < 0)
					break;
			}
			start =  be64_to_cpu(((uint64_t *)buf)[0]);
			end = start + be64_to_cpu(((uint64_t *)buf)[1]);
			add_base_memory_range(start, end);
			fclose(file);
		}
		closedir(dmem);
	}
	closedir(dir);
	sort_base_ranges();
	memory_max = base_memory_range[nr_memory_ranges - 1].end;
	dbgprintf("get base memory ranges:%d\n", nr_memory_ranges);

	return 0;
}
/* Get devtree details and create exclude_range array
 * Also create usablemem_ranges for KEXEC_ON_CRASH
 */
static int get_devtree_details(unsigned long kexec_flags)
{
    uint64_t rmo_base;
    unsigned long long tce_base;
    unsigned int tce_size;
    unsigned long long htab_base, htab_size;
    unsigned long long kernel_end;
    unsigned long long initrd_start, initrd_end;
    char buf[MAXBYTES];
    char device_tree[256] = "/proc/device-tree/";
    char fname[256];
    DIR *dir, *cdir;
    FILE *file;
    struct dirent *dentry;
    int n, i = 0;

    if ((dir = opendir(device_tree)) == NULL) {
        perror(device_tree);
        return -1;
    }

    while ((dentry = readdir(dir)) != NULL) {
        if (strncmp(dentry->d_name, "chosen", 6) &&
                strncmp(dentry->d_name, "memory@", 7) &&
                strncmp(dentry->d_name, "memory", 6) &&
                strncmp(dentry->d_name, "pci@", 4) &&
                strncmp(dentry->d_name, "rtas", 4))
            continue;
        strcpy(fname, device_tree);
        strcat(fname, dentry->d_name);
        if ((cdir = opendir(fname)) == NULL) {
            perror(fname);
            goto error_opendir;
        }

        if (strncmp(dentry->d_name, "chosen", 6) == 0) {
            /* only reserve kernel region if we are doing a crash kernel */
            if (kexec_flags & KEXEC_ON_CRASH) {
                strcat(fname, "/linux,kernel-end");
                file = fopen(fname, "r");
                if (!file) {
                    perror(fname);
                    goto error_opencdir;
                }
                if ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
                    perror(fname);
                    goto error_openfile;
                }
                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 */
                exclude_range[i].start = 0x0UL;
                exclude_range[i].end = kernel_end;
                i++;
                if (i >= max_memory_ranges)
                    realloc_memory_ranges();
                memset(fname, 0, sizeof(fname));
                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 ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
                    perror(fname);
                    goto error_openfile;
                }
                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));
                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 ((n = fread(buf, 1, MAXBYTES, file)) < 0) {
                    perror(fname);
                    goto error_openfile;
                }
                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;
                if (crash_base + crash_size < mem_max)
                    mem_max = crash_base + crash_size;

#ifndef CONFIG_BOOKE
                add_usable_mem_rgns(0, crash_base + crash_size);
                /* Reserve the region (KDUMP_BACKUP_LIMIT,crash_base) */
                reserve(KDUMP_BACKUP_LIMIT,
                        crash_base-KDUMP_BACKUP_LIMIT);
#else
                add_usable_mem_rgns(crash_base, crash_size);
#endif
            }
            /* reserve the initrd_start and end locations. */
            memset(fname, 0, sizeof(fname));
            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;
            }

            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);
                if (errno == ENOENT) {
                    /* Non LPAR */
                    errno = 0;
                    continue;
                }
                perror(fname);
                goto error_opendir;
            }
            if (fread(&htab_base, sizeof(unsigned long), 1, file)
                    != 1) {
                perror(fname);
                goto error_openfile;
            }
            memset(fname, 0, sizeof(fname));
            sprintf(fname, "%s%s%s",
                    device_tree, dentry->d_name,
                    "/linux,htab-size");
            file = fopen(fname, "r");
            if (!file) {
                perror(fname);
                goto error_opencdir;
            }
            if (fread(&htab_size, sizeof(unsigned long), 1, file)
                    != 1) {
                perror(fname);
                goto error_openfile;
            }
            /* Add htab address to exclude_range - NON-LPAR only */
            exclude_range[i].start = htab_base;
            exclude_range[i].end = htab_base + htab_size;
            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) {
                perror(fname);
                goto error_opencdir;
            }
            if (fread(&rtas_base, sizeof(unsigned int), 1, file)
                    != 1) {
                perror(fname);
                goto error_openfile;
            }
            memset(fname, 0, sizeof(fname));
            sprintf(fname, "%s%s%s",
                    device_tree, dentry->d_name,
                    "/linux,rtas-size");
            if ((file = fopen(fname, "r")) == NULL) {
                perror(fname);
                goto error_opencdir;
            }
            if (fread(&rtas_size, sizeof(unsigned int), 1, file)
                    != 1) {
                perror(fname);
                goto error_openfile;
            }
            closedir(cdir);
            /* Add rtas to exclude_range */
            exclude_range[i].start = rtas_base;
            exclude_range[i].end = rtas_base + rtas_size;
            i++;
            if (kexec_flags & KEXEC_ON_CRASH)
                add_usable_mem_rgns(rtas_base, rtas_size);
        } /* rtas */

        if (!strncmp(dentry->d_name, "memory@", 7) ||
                !strcmp(dentry->d_name, "memory")) {
            int fd;
            strcat(fname, "/reg");
            if ((fd = open(fname, O_RDONLY)) < 0) {
                perror(fname);
                goto error_opencdir;
            }
            if (read_memory_region_limits(fd, &rmo_base, &rmo_top) != 0)
                goto error_openfile;

            if (rmo_top > 0x30000000UL)
                rmo_top = 0x30000000UL;

            close(fd);
            closedir(cdir);
        } /* memory */

        if (strncmp(dentry->d_name, "pci@", 4) == 0) {
            strcat(fname, "/linux,tce-base");
            file = fopen(fname, "r");
            if (!file) {
                closedir(cdir);
                if (errno == ENOENT) {
                    /* Non LPAR */
                    errno = 0;
                    continue;
                }
                perror(fname);
                goto error_opendir;
            }
            if (fread(&tce_base, sizeof(unsigned long), 1, file)
                    != 1) {
                perror(fname);
                goto error_openfile;
                return -1;
            }
            memset(fname, 0, sizeof(fname));
            sprintf(fname, "%s%s%s",
                    device_tree, dentry->d_name,
                    "/linux,tce-size");
            file = fopen(fname, "r");
            if (!file) {
                perror(fname);
                goto error_opencdir;
            }
            if (fread(&tce_size, sizeof(unsigned int), 1, file)
                    != 1) {
                perror(fname);
                goto error_openfile;
            }
            /* Add tce to exclude_range - NON-LPAR only */
            exclude_range[i].start = tce_base;
            exclude_range[i].end = tce_base + tce_size;
            i++;
            if (kexec_flags & KEXEC_ON_CRASH)
                add_usable_mem_rgns(tce_base, tce_size);
            closedir(cdir);
        } /* pci */
    }
    closedir(dir);

    nr_exclude_ranges = i;

    sort_ranges();

#ifdef DEBUG
    int k;
    for (k = 0; k < i; k++)
        fprintf(stderr, "exclude_range sorted exclude_range[%d] "
                "start:%llx, end:%llx\n", k, exclude_range[k].start,
                exclude_range[k].end);
#endif
    return 0;

error_openfile:
    fclose(file);
error_opencdir:
    closedir(cdir);
error_opendir:
    closedir(dir);
    return -1;
}
/* Get base memory ranges */
static int get_base_ranges(void)
{
    int local_memory_ranges = 0;
    char device_tree[256] = "/proc/device-tree/";
    char fname[256];
    char buf[MAXBYTES];
    DIR *dir, *dmem;
    struct dirent *dentry, *mentry;
    int n, fd;

    if ((dir = opendir(device_tree)) == NULL) {
        perror(device_tree);
        return -1;
    }
    while ((dentry = readdir(dir)) != NULL) {
        if (strncmp(dentry->d_name, "memory@", 7) &&
                strcmp(dentry->d_name, "memory"))
            continue;
        strcpy(fname, device_tree);
        strcat(fname, dentry->d_name);
        if ((dmem = opendir(fname)) == NULL) {
            perror(fname);
            closedir(dir);
            return -1;
        }
        while ((mentry = readdir(dmem)) != NULL) {
            unsigned long long start, end;

            if (strcmp(mentry->d_name, "reg"))
                continue;
            strcat(fname, "/reg");
            if ((fd = open(fname, O_RDONLY)) < 0) {
                perror(fname);
                closedir(dmem);
                closedir(dir);
                return -1;
            }
            if (read_memory_region_limits(fd, &start, &end) != 0) {
                close(fd);
                closedir(dmem);
                closedir(dir);
                return -1;
            }
            if (local_memory_ranges >= max_memory_ranges) {
                if (realloc_memory_ranges() < 0) {
                    close(fd);
                    break;
                }
            }

            base_memory_range[local_memory_ranges].start = start;
            base_memory_range[local_memory_ranges].end  = end;
            base_memory_range[local_memory_ranges].type = RANGE_RAM;
            local_memory_ranges++;
            dbgprintf("%016llx-%016llx : %x\n",
                      base_memory_range[local_memory_ranges-1].start,
                      base_memory_range[local_memory_ranges-1].end,
                      base_memory_range[local_memory_ranges-1].type);
            close(fd);
        }
        closedir(dmem);
    }
    closedir(dir);
    nr_memory_ranges = local_memory_ranges;
    sort_base_ranges();
    memory_max = base_memory_range[nr_memory_ranges - 1].end;
#ifdef DEBUG
    fprintf(stderr, "get base memory ranges:%d\n", nr_memory_ranges);
#endif
    return 0;
}