Home | History | Annotate | Download | only in memdisk
      1 /* ----------------------------------------------------------------------- *
      2  *
      3  *   Copyright 2001-2008 H. Peter Anvin - All Rights Reserved
      4  *
      5  *   This program is free software; you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
      8  *   Boston MA 02111-1307, USA; either version 2 of the License, or
      9  *   (at your option) any later version; incorporated herein by reference.
     10  *
     11  * ----------------------------------------------------------------------- */
     12 
     13 /*
     14  * msetup.c
     15  *
     16  * Initialization code for memory-based disk
     17  */
     18 
     19 #include <stdint.h>
     20 #ifdef TEST
     21 # include <string.h>
     22 # include <stdio.h>
     23 #else
     24 # include "memdisk.h"
     25 # include "conio.h"
     26 #endif
     27 #include "e820.h"
     28 
     29 uint32_t dos_mem = 0;		/* 0-1MB */
     30 uint32_t low_mem = 0;		/* 1-16MB */
     31 uint32_t high_mem = 0;		/* 16+ MB */
     32 
     33 #ifndef TEST
     34 
     35 static inline int get_e820(void)
     36 {
     37     struct e820_info {
     38 	uint64_t base;
     39 	uint64_t len;
     40 	uint32_t type;
     41     } *buf = sys_bounce;
     42     uint32_t copied;
     43     int range_count = 0;
     44     com32sys_t regs;
     45 
     46     memset(&regs, 0, sizeof regs);
     47     memset(buf, 0, sizeof *buf);
     48 
     49     do {
     50 	regs.eax.l = 0x0000e820;
     51 	regs.ecx.l = sizeof(*buf);
     52 	regs.edx.l = 0x534d4150;
     53 	regs.edi.w[0] = OFFS(buf);
     54 	regs.es = SEG(buf);
     55 
     56 	intcall(0x15, &regs, &regs);
     57 	copied = (regs.eflags.l & 1) ? 0 : regs.ecx.l;
     58 
     59 	if (regs.eax.l != 0x534d4150 || copied < 20)
     60 	    break;
     61 
     62 	printf("e820: %08x%08x %08x%08x %d\n",
     63 	       (uint32_t) (buf->base >> 32), (uint32_t) buf->base,
     64 	       (uint32_t) (buf->len >> 32), (uint32_t) buf->len, buf->type);
     65 
     66 	insertrange(buf->base, buf->len, buf->type);
     67 	range_count++;
     68 
     69     } while (regs.ebx.l);
     70 
     71     return !range_count;
     72 }
     73 
     74 static inline void get_dos_mem(void)
     75 {
     76     com32sys_t regs;
     77 
     78     memset(&regs, 0, sizeof regs);
     79     intcall(0x12, &regs, &regs);
     80     insertrange(0, (uint64_t) ((uint32_t) regs.eax.w[0] << 10), 1);
     81     printf(" DOS: %d K\n", regs.eax.w[0]);
     82 }
     83 
     84 static inline int get_e801(void)
     85 {
     86     int err;
     87     com32sys_t regs;
     88 
     89     memset(&regs, 0, sizeof regs);
     90 
     91     regs.eax.w[0] = 0xe801;
     92     intcall(0x15, &regs, &regs);
     93 
     94     if (!(err = regs.eflags.l & 1)) {
     95 	if (regs.eax.w[0]) {
     96 	    insertrange(0x100000, (uint64_t) ((uint32_t) regs.eax.w[0] << 10),
     97 			1);
     98 	}
     99 	if (regs.ebx.w[0]) {
    100 	    insertrange(0x1000000, (uint64_t) ((uint32_t) regs.ebx.w[0] << 16),
    101 			1);
    102 	}
    103 
    104 	printf("e801: %04x %04x\n", regs.eax.w[0], regs.ebx.w[0]);
    105     }
    106 
    107     return err;
    108 }
    109 
    110 static inline int get_88(void)
    111 {
    112     com32sys_t regs;
    113     int err;
    114 
    115     memset(&regs, 0, sizeof regs);
    116 
    117     regs.eax.b[1] = 0x88;
    118     intcall(0x15, &regs, &regs);
    119 
    120     if (!(err = regs.eflags.l & 1)) {
    121 	if (regs.eax.w[0]) {
    122 	    insertrange(0x100000, (uint64_t) ((uint32_t) regs.eax.w[0] << 10),
    123 			1);
    124 	}
    125 
    126 	printf("  88: %04x\n", regs.eax.w[0]);
    127     }
    128 
    129     return err;
    130 }
    131 
    132 void get_mem(void)
    133 {
    134     if (get_e820()) {
    135 	get_dos_mem();
    136 	if (get_e801()) {
    137 	    if (get_88()) {
    138 		die("MEMDISK: Unable to obtain memory map\n");
    139 	    }
    140 	}
    141     }
    142 }
    143 
    144 #endif /* TEST */
    145 
    146 #define PW(x) (1ULL << (x))
    147 
    148 void parse_mem(void)
    149 {
    150     struct e820range *ep;
    151 
    152     dos_mem = low_mem = high_mem = 0;
    153 
    154     /* Derive "dos mem", "high mem", and "low mem" from the range array */
    155     for (ep = ranges; ep->type != -1U; ep++) {
    156 	if (ep->type == 1) {
    157 	    /* Only look at memory ranges */
    158 	    if (ep->start == 0) {
    159 		if (ep[1].start > PW(20))
    160 		    dos_mem = PW(20);
    161 		else
    162 		    dos_mem = ep[1].start;
    163 	    }
    164 	    if (ep->start <= PW(20) && ep[1].start > PW(20)) {
    165 		if (ep[1].start > PW(24))
    166 		    low_mem = PW(24) - PW(20);
    167 		else
    168 		    low_mem = ep[1].start - PW(20);
    169 	    }
    170 	    if (ep->start <= PW(24) && ep[1].start > PW(24)) {
    171 		if (ep[1].start > PW(32))
    172 		    high_mem = PW(32) - PW(24);
    173 		else
    174 		    high_mem = ep[1].start - PW(24);
    175 	    }
    176 	}
    177     }
    178 }
    179