syslinux/memdisk/msetup.c
<<
>>
Prefs
   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(&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
  74static 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
  84static 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
 110static 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
 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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.