示例#1
0
/**
 * The old /proc/iomem parsing code.
 *
 * @param[out] range pointer that will be set to an array that holds the
 *             memory ranges
 * @param[out] ranges number of ranges valid in @p range
 *
 * @return 0 on success, any other value on failure.
 */
static int get_memory_ranges_proc_iomem(struct memory_range **range, int *ranges)
{
	const char *iomem= proc_iomem();
	int memory_ranges = 0;
	char line[MAX_LINE];
	FILE *fp;
	fp = fopen(iomem, "r");
	if (!fp) {
		fprintf(stderr, "Cannot open %s: %s\n",
			iomem, strerror(errno));
		return -1;
	}
	while(fgets(line, sizeof(line), fp) != 0) {
		unsigned long long start, end;
		char *str;
		int type;
		int consumed;
		int count;
		if (memory_ranges >= MAX_MEMORY_RANGES)
			break;
		count = sscanf(line, "%Lx-%Lx : %n",
			&start, &end, &consumed);
		if (count != 2)
			continue;
		str = line + consumed;
		end = end + 1;
#if 0
		printf("%016Lx-%016Lx : %s",
			start, end, str);
#endif
		if (memcmp(str, "System RAM\n", 11) == 0) {
			type = RANGE_RAM;
		}
		else if (memcmp(str, "reserved\n", 9) == 0) {
			type = RANGE_RESERVED;
		}
		else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
			type = RANGE_ACPI;
		}
		else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
			type = RANGE_ACPI_NVS;
		}
		else {
			continue;
		}
		memory_range[memory_ranges].start = start;
		memory_range[memory_ranges].end = end;
		memory_range[memory_ranges].type = type;
#if 0
		printf("%016Lx-%016Lx : %x\n",
			start, end, type);
#endif
		memory_ranges++;
	}
	fclose(fp);
	*range = memory_range;
	*ranges = memory_ranges;
	return 0;
}
static int get_crash_memory_ranges(int *ranges)
{
	const char *iomem = proc_iomem();
        char line[MAX_LINE];
        FILE *fp;
        unsigned long start, end;

	crash_memory_range = xmalloc(sizeof(struct memory_range) *
				max_memory_ranges);
        fp = fopen(iomem, "r");
        if (!fp) {
                fprintf(stderr, "Cannot open %s: %s\n",
                        iomem, strerror(errno));
                return -1;
        }
	while(fgets(line, sizeof(line), fp) != 0) {
		char *str;
		int type, consumed, count;
		if (memory_ranges >= max_memory_ranges)
			break;
		count = sscanf(line, "%lx-%lx : %n",
				&start, &end, &consumed);
		str = line + consumed;
		if (count != 2)
			continue;

		if (memcmp(str, "System RAM\n", 11) == 0) {
			type = RANGE_RAM;
		} else if (memcmp(str, "Crash kernel\n", 13) == 0) {
			/* Reserved memory region. New kernel can
			 * use this region to boot into. */
			crash_reserved_mem.start = start;
			crash_reserved_mem.end = end;
			crash_reserved_mem.type = RANGE_RAM;
			continue;
		}
		else if (memcmp(str, "Kernel code\n", 12) == 0) {
			kernel_code_start = start;
			kernel_code_end = end;
			continue;
		} else if (memcmp(str, "Uncached RAM\n", 13) == 0) {
			type = RANGE_UNCACHED;
		} else {
			continue;
		}
		crash_memory_range[memory_ranges].start = start;
		crash_memory_range[memory_ranges].end = end;
		crash_memory_range[memory_ranges].type = type;
		memory_ranges++;
	}
        fclose(fp);
	if (exclude_crash_reserve_region(&memory_ranges) < 0)
		return -1;
	*ranges = memory_ranges;
	return 0;
}
示例#3
0
/* Return a sorted list of available memory ranges. */
int get_memory_ranges(struct memory_range **range, int *ranges,
		unsigned long kexec_flags)
{
	const char *iomem = proc_iomem();
	int memory_ranges = 0;
	char line[MAX_LINE];
	FILE *fp;
	fp = fopen(iomem, "r");
	if (!fp) {
		fprintf(stderr, "Cannot open %s: %s\n",
			iomem, strerror(errno));
		return -1;
	}

	while(fgets(line, sizeof(line), fp) != 0) {
		unsigned long long start, end;
		char *str;
		int type;
		int consumed;
		int count;
		if (memory_ranges >= MAX_MEMORY_RANGES)
			break;
		count = sscanf(line, "%Lx-%Lx : %n",
			&start, &end, &consumed);
		if (count != 2)
			continue;
		str = line + consumed;
		end = end + 1;

		if (memcmp(str, "System RAM\n", 11) == 0) {
			type = RANGE_RAM;
		}
		else if (memcmp(str, "reserved\n", 9) == 0) {
			type = RANGE_RESERVED;
		}
		else {
			continue;
		}

		memory_range[memory_ranges].start = start;
		memory_range[memory_ranges].end = end;
		memory_range[memory_ranges].type = type;
		memory_ranges++;
	}
	fclose(fp);
	*range = memory_range;
	*ranges = memory_ranges;
	return 0;
}
int kexec_iomem_for_each_line(char *match,
			      int (*callback)(void *data,
					      int nr,
					      char *str,
					      unsigned long base,
					      unsigned long length),
			      void *data)
{
	const char *iomem = proc_iomem();
	char line[MAX_LINE];
	FILE *fp;
	unsigned long long start, end, size;
	char *str;
	int consumed;
	int count;
	int nr = 0;

	fp = fopen(iomem, "r");
	if (!fp)
		die("Cannot open %s\n", iomem);

	while(fgets(line, sizeof(line), fp) != 0) {
#ifdef ANDROID
		count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed);
#else
		count = sscanf(line, "%Lx-%Lx : %n", &start, &end, &consumed);
#endif
		if (count != 2)
			continue;
		str = line + consumed;
		size = end - start + 1;
		if (!match || memcmp(str, match, strlen(match)) == 0) {
			if (callback
			    && callback(data, nr, str, start, size) < 0) {
				break;
			}
			nr++;
		}
	}

	fclose(fp);

	return nr;
}
int get_memory_ranges(struct memory_range **range, int *ranges,
		      unsigned long UNUSED(flags))
{
	char sys_ram[] = "System RAM\n";
	const char *iomem = proc_iomem();
	FILE *fp;
	char line[80];
	int current_range = 0;

	fp = fopen(iomem,"r");
	if(fp == 0) {
		fprintf(stderr,"Unable to open %s: %s\n",iomem,strerror(errno));
		return -1;
	}

	/* Setup the compare string properly. */
	while(fgets(line,sizeof(line),fp) != 0) {
		unsigned long long start, end;
		int cons;
		char *str;

		if (current_range == MAX_MEMORY_RANGES)
			break;

		sscanf(line,"%Lx-%Lx : %n", &start, &end, &cons);
		str = line+cons;
		if(memcmp(str,sys_ram,strlen(sys_ram)) == 0) {
			memory_range[current_range].start = start;
			memory_range[current_range].end = end;
			memory_range[current_range].type = RANGE_RAM;
			current_range++;
		}
		else {
			continue;
		}
	}
	fclose(fp);
	*range = memory_range;
	*ranges = current_range;

	return 0;
}
示例#6
0
int elf_ia64_load(int argc, char **argv, const char *buf, off_t len,
	struct kexec_info *info)
{
	struct mem_ehdr ehdr;
	const char *command_line, *ramdisk=0, *vmm=0, *kernel_buf;
	char *ramdisk_buf = NULL;
	off_t ramdisk_size = 0, kernel_size;
	unsigned long command_line_len;
	unsigned long entry, max_addr, gp_value;
	unsigned long command_line_base, ramdisk_base, image_base;
	unsigned long efi_memmap_base, efi_memmap_size;
	unsigned long boot_param_base;
	unsigned long noio=0;
	int result;
	int opt;
	char *efi_memmap_buf, *boot_param;
	static const struct option options[] = {
		KEXEC_ARCH_OPTIONS
		{"command-line", 1, 0, OPT_APPEND},
		{"append",       1, 0, OPT_APPEND},
		{"initrd",       1, 0, OPT_RAMDISK},
		{"noio",         0, 0, OPT_NOIO},
		{"vmm",          1, 0, OPT_VMM},
		{0, 0, 0, 0},
	};

	static const char short_options[] = KEXEC_ARCH_OPT_STR "";

	command_line = 0;
	while ((opt = getopt_long(argc, argv, short_options,
				  options, 0)) != -1) {
		switch (opt) {
		default:
			/* Ignore core options */
			if (opt < OPT_ARCH_MAX) {
				break;
			}
		case '?':
			usage();
			return -1;
		case OPT_APPEND:
			command_line = optarg;
			break;
		case OPT_RAMDISK:
			ramdisk = optarg;
			break;
		case OPT_NOIO:	/* disable PIO and MMIO in purgatory code*/
			noio = 1;
			break;
		case OPT_VMM:
			vmm = optarg;
			break;
		}
	}
	command_line_len = 0;
	if (command_line) {
		command_line_len = strlen(command_line) + 16;
	}

	if (vmm)
		kernel_buf = slurp_decompress_file(vmm, &kernel_size);
	else {
		kernel_buf = buf;
		kernel_size = len;
	}

	/* Parse the Elf file */
	result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
	if (result < 0) {
		fprintf(stderr, "ELF parse failed\n");
		free_elf_info(&ehdr);
		return result;
	}

	if (info->kexec_flags & KEXEC_ON_CRASH ) {
		if ((mem_min == 0x00) && (mem_max == ULONG_MAX)) {
			fprintf(stderr, "Failed to find crash kernel region "
				"in %s\n", proc_iomem());
			free_elf_info(&ehdr);
			return -1;
		}
		move_loaded_segments(info, &ehdr, mem_min);
	} else if (update_loaded_segments(info, &ehdr) < 0) {
		fprintf(stderr, "Failed to place kernel\n");
		return -1;
	}

	entry = ehdr.e_entry;
	max_addr = elf_max_addr(&ehdr);

	/* Load the Elf data */
	result = elf_exec_load(&ehdr, info);
	if (result < 0) {
		fprintf(stderr, "ELF load failed\n");
		free_elf_info(&ehdr);
		return result;
	}


	/* Load the setup code */
	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
			0x0, ULONG_MAX, -1, 0);


	if (load_crashdump_segments(info, &ehdr, max_addr, 0,
				&command_line) < 0)
		return -1;

	// reverve 4k for ia64_boot_param
	boot_param = xmalloc(4096);
        boot_param_base = add_buffer(info, boot_param, 4096, 4096, 4096, 0,
                        max_addr, -1);

	elf_rel_set_symbol(&info->rhdr, "__noio",
			   &noio, sizeof(long));

        elf_rel_set_symbol(&info->rhdr, "__boot_param_base",
                        &boot_param_base, sizeof(long));

	// reserve efi_memmap of actual size allocated in production kernel
	efi_memmap_size = saved_efi_memmap_size;
	efi_memmap_buf = xmalloc(efi_memmap_size);
	efi_memmap_base = add_buffer(info, efi_memmap_buf,
			efi_memmap_size, efi_memmap_size, 4096, 0,
			max_addr, -1);

	elf_rel_set_symbol(&info->rhdr, "__efi_memmap_base",
			&efi_memmap_base, sizeof(long));

	elf_rel_set_symbol(&info->rhdr, "__efi_memmap_size",
			&efi_memmap_size, sizeof(long));
	if (command_line) {
		command_line_len = strlen(command_line) + 1;
	}
	if (command_line_len || (info->kexec_flags & KEXEC_ON_CRASH )) {
		char *cmdline = xmalloc(command_line_len);
		strcpy(cmdline, command_line);

		if (info->kexec_flags & KEXEC_ON_CRASH) {
			char buf[128];
			sprintf(buf," max_addr=%lluM min_addr=%lluM",
					mem_max>>20, mem_min>>20);
			command_line_len = strlen(cmdline) + strlen(buf) + 1;
			cmdline = xrealloc(cmdline, command_line_len);
			strcat(cmdline, buf);
		}
/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
 * create Elf headers. Keeping it separate from get_memory_ranges() as
 * requirements are different in the case of normal kexec and crashdumps.
 *
 * Normal kexec needs to look at all of available physical memory irrespective
 * of the fact how much of it is being used by currently running kernel.
 * Crashdumps need to have access to memory regions actually being used by
 * running  kernel. Expecting a different file/data structure than /proc/iomem
 * to look into down the line. May be something like /proc/kernelmem or may
 * be zone data structures exported from kernel.
 */
static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
				   int kexec_flags)
{
	const char *iomem= proc_iomem();
	int memory_ranges = 0, gart = 0;
	char line[MAX_LINE];
	FILE *fp;
	unsigned long long start, end;
	uint64_t gart_start = 0, gart_end = 0;

	fp = fopen(iomem, "r");
	if (!fp) {
		fprintf(stderr, "Cannot open %s: %s\n",
			iomem, strerror(errno));
		return -1;
	}

	/* First entry is for first 640K region. Different bios report first
	 * 640K in different manner hence hardcoding it */
	if (!(kexec_flags & KEXEC_PRESERVE_CONTEXT)) {
		crash_memory_range[0].start = 0x00000000;
		crash_memory_range[0].end = 0x0009ffff;
		crash_memory_range[0].type = RANGE_RAM;
		memory_ranges++;
	}

	while(fgets(line, sizeof(line), fp) != 0) {
		char *str;
		int type, consumed, count;

		if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
			break;
		count = sscanf(line, "%Lx-%Lx : %n",
			&start, &end, &consumed);
		if (count != 2)
			continue;
		str = line + consumed;
#ifdef DEBUG
		printf("%016Lx-%016Lx : %s",
			start, end, str);
#endif
		/* Only Dumping memory of type System RAM. */
		if (memcmp(str, "System RAM\n", 11) == 0) {
			type = RANGE_RAM;
		} else if (memcmp(str, "Crash kernel\n", 13) == 0) {
				/* Reserved memory region. New kernel can
				 * use this region to boot into. */
				crash_reserved_mem.start = start;
				crash_reserved_mem.end = end;
				crash_reserved_mem.type = RANGE_RAM;
				continue;
		} else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
			/*
			 * ACPI Tables area need to be passed to new
			 * kernel with appropriate memmap= option. This
			 * is needed so that x86_64 kernel creates linear
			 * mapping for this region which is required for
			 * initializing acpi tables in second kernel.
			 */
			type = RANGE_ACPI;
		} else if(memcmp(str,"ACPI Non-volatile Storage\n",26) == 0 ) {
			type = RANGE_ACPI_NVS;
		} else if (memcmp(str, "GART\n", 5) == 0) {
			gart_start = start;
			gart_end = end;
			gart = 1;
			continue;
		} else {
			continue;
		}

		/* First 640K already registered */
		if (end <= 0x0009ffff)
			continue;

		crash_memory_range[memory_ranges].start = start;
		crash_memory_range[memory_ranges].end = end;
		crash_memory_range[memory_ranges].type = type;
		memory_ranges++;
	}
	fclose(fp);
	if (kexec_flags & KEXEC_PRESERVE_CONTEXT) {
		int i;
		for (i = 0; i < memory_ranges; i++) {
			if (crash_memory_range[i].end > 0x0009ffff) {
				crash_reserved_mem.start = \
					crash_memory_range[i].start;
				break;
			}
		}
		if (crash_reserved_mem.start >= mem_max) {
			fprintf(stderr, "Too small mem_max: 0x%llx.\n", mem_max);
			return -1;
		}
		crash_reserved_mem.end = mem_max;
		crash_reserved_mem.type = RANGE_RAM;
	}
	if (exclude_region(&memory_ranges, crash_reserved_mem.start,
				crash_reserved_mem.end) < 0)
		return -1;
	if (gart) {
		/* exclude GART region if the system has one */
		if (exclude_region(&memory_ranges, gart_start, gart_end) < 0)
			return -1;
	}
	*range = crash_memory_range;
	*ranges = memory_ranges;
#ifdef DEBUG
	int i;
	printf("CRASH MEMORY RANGES\n");
	for(i = 0; i < memory_ranges; i++) {
		start = crash_memory_range[i].start;
		end = crash_memory_range[i].end;
		printf("%016Lx-%016Lx\n", start, end);
	}
#endif
	return 0;
}
/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
 * create Elf headers. Keeping it separate from get_memory_ranges() as
 * requirements are different in the case of normal kexec and crashdumps.
 *
 * Normal kexec needs to look at all of available physical memory irrespective
 * of the fact how much of it is being used by currently running kernel.
 * Crashdumps need to have access to memory regions actually being used by
 * running  kernel. Expecting a different file/data structure than /proc/iomem
 * to look into down the line. May be something like /proc/kernelmem or may
 * be zone data structures exported from kernel.
 */
static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
{
    const char *iomem = proc_iomem();
    int memory_ranges = 0;
    char line[MAX_LINE];
    FILE *fp;
    unsigned long long start, end;

    fp = fopen(iomem, "r");
    if (!fp) {
        fprintf(stderr, "Cannot open %s: %s\n",
                iomem, strerror(errno));
        return -1;
    }

    /* First entry is for first 640K region. Different bios report first
     * 640K in different manner hence hardcoding it */
    crash_memory_range[0].start = 0x00000000;
    crash_memory_range[0].end = 0x0009ffff;
    crash_memory_range[0].type = RANGE_RAM;
    memory_ranges++;

    while(fgets(line, sizeof(line), fp) != 0) {
        char *str;
        int type, consumed, count;
        if (memory_ranges >= CRASH_MAX_MEMORY_RANGES)
            break;
        count = sscanf(line, "%Lx-%Lx : %n",
                       &start, &end, &consumed);
        if (count != 2)
            continue;
        str = line + consumed;
#if 0
        printf("%016Lx-%016Lx : %s",
               start, end, str);
#endif
        /* Only Dumping memory of type System RAM. */
        if (memcmp(str, "System RAM\n", 11) == 0) {
            type = RANGE_RAM;
        } else if (memcmp(str, "Crash kernel\n", 13) == 0) {
            /* Reserved memory region. New kernel can
             * use this region to boot into. */
            crash_reserved_mem.start = start;
            crash_reserved_mem.end = end;
            crash_reserved_mem.type = RANGE_RAM;
            continue;
        } else {
            continue;
        }

        /* First 640K already registered */
        if (start >= 0x00000000 && end <= 0x0009ffff)
            continue;

        crash_memory_range[memory_ranges].start = start;
        crash_memory_range[memory_ranges].end = end;
        crash_memory_range[memory_ranges].type = type;
        memory_ranges++;

        /* Segregate linearly mapped region. */
        if ((MAXMEM - 1) >= start && (MAXMEM - 1) <= end) {
            crash_memory_range[memory_ranges-1].end = MAXMEM -1;

            /* Add segregated region. */
            crash_memory_range[memory_ranges].start = MAXMEM;
            crash_memory_range[memory_ranges].end = end;
            crash_memory_range[memory_ranges].type = type;
            memory_ranges++;
        }
    }
    fclose(fp);
    if (exclude_crash_reserve_region(&memory_ranges) < 0)
        return -1;
    *range = crash_memory_range;
    *ranges = memory_ranges;
#if 0
    int i;
    printf("CRASH MEMORY RANGES\n");
    for(i = 0; i < memory_ranges; i++) {
        start = crash_memory_range[i].start;
        end = crash_memory_range[i].end;
        printf("%016Lx-%016Lx\n", start, end);
    }
#endif
    return 0;
}
/* Return a sorted list of available memory ranges. */
int get_memory_ranges(struct memory_range **range, int *ranges,
				unsigned long kexec_flags)
{
	const char *iomem = proc_iomem();
	char line[MAX_LINE];
	FILE *fp;
	fp = fopen(iomem, "r");
	if (!fp) {
		fprintf(stderr, "Cannot open %s: %s\n",
			iomem, strerror(errno));
		return -1;
	}

	/* allocate memory_range dynamically */
	max_memory_ranges = 0;
	while(fgets(line, sizeof(line), fp) != 0) {
		max_memory_ranges++;
	}
	memory_range = xmalloc(sizeof(struct memory_range) *
			max_memory_ranges);
	rewind(fp);

	while(fgets(line, sizeof(line), fp) != 0) {
		unsigned long start, end;
		char *str;
		unsigned type;
		int consumed;
		int count;
		if (memory_ranges >= max_memory_ranges)
			break;
		count = sscanf(line, "%lx-%lx : %n",
				&start, &end, &consumed);
		if (count != 2)
			continue;
		str = line + consumed;
		end = end + 1;
		if (memcmp(str, "System RAM\n", 11) == 0) {
			type = RANGE_RAM;
		}
		else if (memcmp(str, "reserved\n", 9) == 0) {
			type = RANGE_RESERVED;
		}
		else if (memcmp(str, "Crash kernel\n", 13) == 0) {
			/* Redefine the memory region boundaries if kernel
			 * exports the limits and if it is panic kernel.
			 * Override user values only if kernel exported
			 * values are subset of user defined values.
			 */

			if (kexec_flags & KEXEC_ON_CRASH) {
				if (start > mem_min)
					mem_min = start;
				if (end < mem_max)
					mem_max = end;
			}
			continue;
		} else if (memcmp(str, "Boot parameter\n", 14) == 0) {
			memory_ranges = split_range(memory_ranges, start, end);
			continue;
		} else if (memcmp(str, "EFI Memory Map\n", 14) == 0) {
			memory_ranges = split_range(memory_ranges, start, end);
			saved_efi_memmap_size = end - start;
			continue;
		} else if (memcmp(str, "Uncached RAM\n", 13) == 0) {
			type = RANGE_UNCACHED;
		} else {
			continue;
		}
		/*
		 * Check if this memory range can be coalesced with
		 * the previous range
		 */
		if ((memory_ranges > 0) &&
			(start == memory_range[memory_ranges-1].end) &&
			(type == memory_range[memory_ranges-1].type)) {
			memory_range[memory_ranges-1].end = end;
		}
		else {
			memory_range[memory_ranges].start = start;
			memory_range[memory_ranges].end = end;
			memory_range[memory_ranges].type = type;
			memory_ranges++;
		}
	}
	fclose(fp);
 	*range = memory_range;
 	*ranges = memory_ranges;

 	return 0;
}
/* Return a sorted list of memory ranges. */
int get_memory_ranges(struct memory_range **range, int *ranges,
					unsigned long kexec_flags)
{
	const char *iomem= proc_iomem();
	int memory_ranges = 0;
	char line[MAX_LINE];
	FILE *fp;
	fp = fopen(iomem, "r");
	if (!fp) {
		fprintf(stderr, "Cannot open %s: %s\n", 
			iomem, strerror(errno));
		return -1;
	}
	while(fgets(line, sizeof(line), fp) != 0) {
		unsigned long long start, end;
		char *str;
		int type;
		int consumed;
		int count;
		if (memory_ranges >= MAX_MEMORY_RANGES)
			break;
		count = sscanf(line, "%Lx-%Lx : %n",
			&start, &end, &consumed);
		if (count != 2) 
			continue;
		str = line + consumed;
		end = end + 1;
#ifdef DEBUG
		printf("%016Lx-%016Lx : %s",
			start, end, str);
#endif
		if (memcmp(str, "System RAM\n", 11) == 0) {
			type = RANGE_RAM;
		} 
		else if (memcmp(str, "reserved\n", 9) == 0) {
			type = RANGE_RESERVED;
		}
		else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
			type = RANGE_ACPI;
		}
		else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) {
			type = RANGE_ACPI_NVS;
		}
		else if (memcmp(str, "Crash kernel\n", 13) == 0) {
			/* Redefine the memory region boundaries if kernel
			 * exports the limits and if it is panic kernel.
			 * Override user values only if kernel exported
			 * values are subset of user defined values.
			 */
			if (kexec_flags & KEXEC_ON_CRASH) {
				if (start > mem_min)
					mem_min = start;
				if (end < mem_max)
					mem_max = end;
			}
			continue;
		}
		else {
			continue;
		}
		/* Don't report the interrupt table as ram */
		if (type == RANGE_RAM && (start < 0x100)) {
			start = 0x100;
		}
		memory_range[memory_ranges].start = start;
		memory_range[memory_ranges].end = end;
		memory_range[memory_ranges].type = type;
#ifdef DEBUG
		printf("%016Lx-%016Lx : %x\n",
			start, end, type);
#endif
		memory_ranges++;
	}
	fclose(fp);
	*range = memory_range;
	*ranges = memory_ranges;
	return 0;
}