Fork me on GitHub

root/mm/bios_map.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. addr_in_bios_map
  2. bios_map_add
  3. bios_map_init

   1 /*
   2  * fiwix/mm/bios_map.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/kernel.h>
   9 #include <fiwix/mm.h>
  10 #include <fiwix/bios.h>
  11 #include <fiwix/stdio.h>
  12 #include <fiwix/string.h>
  13 
  14 static char *bios_mem_type[] = {
  15         NULL,
  16         "available",
  17         "reserved",
  18         "ACPI Reclaim",
  19         "ACPI NVS",
  20         "unusable",
  21         "disabled"
  22 };
  23 
  24 /* check if an specific address is available in the BIOS memory map */
  25 int addr_in_bios_map(unsigned int addr)
  26 {
  27         int n, retval;
  28         struct bios_mem_map *bmm;
  29 
  30         retval = 0;
  31         bmm = &bios_mem_map[0];
  32 
  33         for(n = 0; n < NR_BIOS_MM_ENT; n++, bmm++) {
  34                 if(bmm->to && bmm->type == MULTIBOOT_MEMORY_AVAILABLE) {
  35                         if(addr >= bmm->from && addr < (bmm->to & PAGE_MASK)) {
  36                                 retval = 1;
  37                         }
  38                 }
  39         }
  40 
  41         /* this second pass is necessary because the array is not sorted */
  42         bmm = &bios_mem_map[0];
  43         for(n = 0; n < NR_BIOS_MM_ENT; n++, bmm++) {
  44                 if(bmm->to && bmm->type == MULTIBOOT_MEMORY_RESERVED) {
  45                         if(addr >= bmm->from && addr < (bmm->to & PAGE_MASK)) {
  46                                 retval = 0;
  47                         }
  48                 }
  49         }
  50 
  51         return retval;  /* not in BIOS map or not available (reserved, ...) */
  52 }
  53 
  54 void bios_map_add(unsigned long int from, unsigned long int to, int from_type, int to_type)
  55 {
  56         int n;
  57 
  58         for(n = 0; n < NR_BIOS_MM_ENT; n++) {
  59                 if(!bios_mem_map[n].type) {
  60                         break;
  61                 }
  62         }
  63 
  64         if(from_type == to_type) {
  65                 printk("memory    0x%08X%08X-0x%08X%08X %s\n",
  66                         0, from,
  67                         0, to,
  68                         bios_mem_type[to_type]
  69                 );
  70         } else {
  71                 printk("memory    0x%08X%08X-0x%08X%08X %s -> %s\n",
  72                         0, from,
  73                         0, to,
  74                         bios_mem_type[from_type],
  75                         bios_mem_type[to_type]
  76                 );
  77         }
  78         bios_mem_map[n].from = from;
  79         bios_mem_map[n].to = to;
  80         bios_mem_map[n].type = to_type;
  81 }
  82 
  83 void bios_map_init(struct multiboot_mmap_entry *bmmap_addr, unsigned long int bmmap_length)
  84 {
  85         struct multiboot_mmap_entry *bmmap;
  86         unsigned int from_high, from_low, to_high, to_low;
  87         unsigned long long to;
  88         int n;
  89 
  90         bmmap = bmmap_addr;
  91         kstat.physical_pages = 0;
  92 
  93         if(bmmap) {
  94                 n = 0;
  95 
  96                 while((unsigned int)bmmap < (unsigned int)bmmap_addr + bmmap_length) {
  97                         from_high = (unsigned int)(bmmap->addr >> 32);
  98                         from_low = (unsigned int)(bmmap->addr & 0xFFFFFFFF);
  99                         to = bmmap->addr + bmmap->len;
 100                         to_high = (unsigned int)(to >> 32);
 101                         to_low = (unsigned int)(to & 0xFFFFFFFF);
 102                         printk("%s    0x%08X%08X-0x%08X%08X %s\n",
 103                                 n ? "      " : "memory",
 104                                 from_high,
 105                                 from_low,
 106                                 to_high,
 107                                 to_low,
 108                                 bios_mem_type[(int)bmmap->type]
 109                         );
 110                         /* only memory addresses below 4GB are counted */
 111                         if(!from_high && !to_high) {
 112                                 if(n < NR_BIOS_MM_ENT && bmmap->len) {
 113                                         bios_mem_map[n].from = from_low;
 114                                         bios_mem_map[n].to = to_low;
 115                                         bios_mem_map[n].type = (int)bmmap->type;
 116                                         if(bios_mem_map[n].type == MULTIBOOT_MEMORY_AVAILABLE) {
 117                                                 from_low = bios_mem_map[n].from & PAGE_MASK;
 118                                                 to_low = bios_mem_map[n].to & PAGE_MASK;
 119 
 120                                                 /* the first MB is not counted here */
 121                                                 if(from_low >= 0x100000) {
 122                                                         kstat.physical_pages += (to_low - from_low) / PAGE_SIZE;
 123                                                 }
 124                                         }
 125                                         n++;
 126                                 }
 127                         }
 128                         bmmap = (struct multiboot_mmap_entry *)((unsigned int)bmmap + bmmap->size + sizeof(bmmap->size));
 129                 }
 130                 kstat.physical_pages += (1024 >> 2);    /* add the first MB as a whole */
 131                 if(kstat.physical_pages > (0x40000000 >> PAGE_SHIFT)) {
 132                         printk("WARNING: detected a total of %dMB of available memory below 4GB.\n", (kstat.physical_pages << 2) / 1024);
 133                 }
 134         } else {
 135                 printk("WARNING: your BIOS has not provided a memory map.\n");
 136                 bios_mem_map[0].from = 0;
 137                 bios_mem_map[0].to = _memsize * 1024;
 138                 bios_mem_map[0].type = MULTIBOOT_MEMORY_AVAILABLE;
 139                 bios_mem_map[1].from = 0x00100000;
 140                 bios_mem_map[1].to = (_extmemsize + 1024) * 1024;
 141                 bios_mem_map[1].type = MULTIBOOT_MEMORY_AVAILABLE;
 142                 kstat.physical_pages = (_extmemsize + 1024) >> 2;
 143         }
 144 
 145         /*
 146          * This truncates to 1GB since it's the maximum physical memory
 147          * currently supported.
 148          */
 149         if(kstat.physical_pages > (0x40000000 >> PAGE_SHIFT)) {
 150                 kstat.physical_pages = (0x40000000 >> PAGE_SHIFT);
 151                 printk("WARNING: only up to 1GB of physical memory will be used.\n");
 152         }
 153 }

/* [previous][next][first][last][top][bottom][index][help] */