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 29uint32_t dos_mem = 0; /* 0-1MB */ 30uint32_t low_mem = 0; /* 1-16MB */ 31uint32_t high_mem = 0; /* 16+ MB */ 32 33#ifndef TEST 34 35static 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(®s, 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, ®s, ®s); 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 74static inline void get_dos_mem(void) 75{ 76 com32sys_t regs; 77 78 memset(®s, 0, sizeof regs); 79 intcall(0x12, ®s, ®s); 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 84static inline int get_e801(void) 85{ 86 int err; 87 com32sys_t regs; 88 89 memset(®s, 0, sizeof regs); 90 91 regs.eax.w[0] = 0xe801; 92 intcall(0x15, ®s, ®s); 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 110static inline int get_88(void) 111{ 112 com32sys_t regs; 113 int err; 114 115 memset(®s, 0, sizeof regs); 116 117 regs.eax.b[1] = 0x88; 118 intcall(0x15, ®s, ®s); 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 132void 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 148void 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