/**     
 *      memparse - parse a string with mem suffixes into a number
 *      @ptr: Where parse begins
 *      @retptr: (output) Optional pointer to next char after parse completes
 *
 *      Parses a string into a number.  The number stored at @ptr is
 *      potentially suffixed with %K (for kilobytes, or 1024 bytes),
 *      %M (for megabytes, or 1048576 bytes), or %G (for gigabytes, or
 *      1073741824).  If the number is suffixed with K, M, or G, then
 *      the return value is the number multiplied by one kilobyte, one
 *      megabyte, or one gigabyte, respectively.
 */
        
unsigned long long memparse(const char *ptr, char **retptr)
{       
        char *endptr;   /* local pointer to end of parsed string */
        
        unsigned long long ret = simple_strtoull(ptr, &endptr, 0);

        switch (*endptr) {
        case 'G':
        case 'g':
                ret <<= 10;
        case 'M':
        case 'm':
                ret <<= 10;
        case 'K':
        case 'k':
                ret <<= 10;
                endptr++;
        default:
                break;
        }

        if (retptr)
                *retptr = endptr;

        return ret;
}               
                


static int __init parse_memmap_opt(char *p)
{
        char *oldp;
        u64 start_at, mem_size;

        if (!p)
                return -EINVAL;

        if (!strncmp(p, "exactmap", 8)) {
#ifdef CONFIG_CRASH_DUMP
                /*
                 * If we are doing a crash dump, we still need to know
                 * the real mem size before original memory map is
                 * reset.
                 */
                saved_max_pfn = e820_end_of_ram_pfn();
#endif
                e820.nr_map = 0;
                userdef = 1;
                return 0;
        }

        oldp = p;
        mem_size = memparse(p, &p);
        if (p == oldp)
                return -EINVAL;

        userdef = 1;
        if (*p == '@') {
                start_at = memparse(p+1, &p);
                e820_add_region(start_at, mem_size, E820_RAM);
        } else if (*p == '#') {
                start_at = memparse(p+1, &p);
                e820_add_region(start_at, mem_size, E820_ACPI);
        } else if (*p == '$') {
                start_at = memparse(p+1, &p);
                e820_add_region(start_at, mem_size, E820_RESERVED);
        } else
                e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);

        return *p == '\0' ? 0 : -EINVAL;
}
early_param("memmap", parse_memmap_opt);

/* "mem=nopentium" disables the 4MB page tables. */
static int __init parse_memopt(char *p)
{
        u64 mem_size;

        if (!p)
                return -EINVAL;

#ifdef CONFIG_X86_32
        if (!strcmp(p, "nopentium")) {
                setup_clear_cpu_cap(X86_FEATURE_PSE);
                return 0;
        }
#endif

        userdef = 1;
        mem_size = memparse(p, &p);
        e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);

        return 0;
}
early_param("mem", parse_memopt);


Reply via email to