Annotation of qemu/roms/seabios/src/memmap.c, revision 1.1

1.1     ! root        1: // Support for building memory maps suitable for int 15 e820 calls.
        !             2: //
        !             3: // Copyright (C) 2008,2009  Kevin O'Connor <[email protected]>
        !             4: //
        !             5: // This file may be distributed under the terms of the GNU LGPLv3 license.
        !             6: 
        !             7: #include "memmap.h" // struct e820entry
        !             8: #include "util.h" // dprintf.h
        !             9: #include "biosvar.h" // SET_EBDA
        !            10: 
        !            11: 
        !            12: /****************************************************************
        !            13:  * e820 memory map
        !            14:  ****************************************************************/
        !            15: 
        !            16: // Remove an entry from the e820_list.
        !            17: static void
        !            18: remove_e820(int i)
        !            19: {
        !            20:     e820_count--;
        !            21:     memmove(&e820_list[i], &e820_list[i+1]
        !            22:             , sizeof(e820_list[0]) * (e820_count - i));
        !            23: }
        !            24: 
        !            25: // Insert an entry in the e820_list at the given position.
        !            26: static void
        !            27: insert_e820(int i, u64 start, u64 size, u32 type)
        !            28: {
        !            29:     if (e820_count >= CONFIG_MAX_E820) {
        !            30:         dprintf(1, "Overflowed e820 list!\n");
        !            31:         return;
        !            32:     }
        !            33: 
        !            34:     memmove(&e820_list[i+1], &e820_list[i]
        !            35:             , sizeof(e820_list[0]) * (e820_count - i));
        !            36:     e820_count++;
        !            37:     struct e820entry *e = &e820_list[i];
        !            38:     e->start = start;
        !            39:     e->size = size;
        !            40:     e->type = type;
        !            41: }
        !            42: 
        !            43: // Show the current e820_list.
        !            44: static void
        !            45: dump_map()
        !            46: {
        !            47:     dprintf(1, "e820 map has %d items:\n", e820_count);
        !            48:     int i;
        !            49:     for (i=0; i<e820_count; i++) {
        !            50:         struct e820entry *e = &e820_list[i];
        !            51:         u64 e_end = e->start + e->size;
        !            52:         dprintf(1, "  %d: %08x%08x - %08x%08x = %d\n", i
        !            53:                 , (u32)(e->start >> 32), (u32)e->start
        !            54:                 , (u32)(e_end >> 32), (u32)e_end
        !            55:                 , e->type);
        !            56:     }
        !            57: }
        !            58: 
        !            59: // Add a new entry to the list.  This scans for overlaps and keeps the
        !            60: // list sorted.
        !            61: void
        !            62: add_e820(u64 start, u64 size, u32 type)
        !            63: {
        !            64:     dprintf(8, "Add to e820 map: %08x %08x %d\n", (u32)start, (u32)size, type);
        !            65: 
        !            66:     if (! size)
        !            67:         // Huh?  Nothing to do.
        !            68:         return;
        !            69: 
        !            70:     // Find position of new item (splitting existing item if needed).
        !            71:     u64 end = start + size;
        !            72:     int i;
        !            73:     for (i=0; i<e820_count; i++) {
        !            74:         struct e820entry *e = &e820_list[i];
        !            75:         u64 e_end = e->start + e->size;
        !            76:         if (start > e_end)
        !            77:             continue;
        !            78:         // Found position - check if an existing item needs to be split.
        !            79:         if (start > e->start) {
        !            80:             if (type == e->type) {
        !            81:                 // Same type - merge them.
        !            82:                 size += start - e->start;
        !            83:                 start = e->start;
        !            84:             } else {
        !            85:                 // Split existing item.
        !            86:                 e->size = start - e->start;
        !            87:                 i++;
        !            88:                 if (e_end > end)
        !            89:                     insert_e820(i, end, e_end - end, e->type);
        !            90:             }
        !            91:         }
        !            92:         break;
        !            93:     }
        !            94:     // Remove/adjust existing items that are overlapping.
        !            95:     while (i<e820_count) {
        !            96:         struct e820entry *e = &e820_list[i];
        !            97:         if (end < e->start)
        !            98:             // No overlap - done.
        !            99:             break;
        !           100:         u64 e_end = e->start + e->size;
        !           101:         if (end >= e_end) {
        !           102:             // Existing item completely overlapped - remove it.
        !           103:             remove_e820(i);
        !           104:             continue;
        !           105:         }
        !           106:         // Not completely overlapped - adjust its start.
        !           107:         e->start = end;
        !           108:         e->size = e_end - end;
        !           109:         if (type == e->type) {
        !           110:             // Same type - merge them.
        !           111:             size += e->size;
        !           112:             remove_e820(i);
        !           113:         }
        !           114:         break;
        !           115:     }
        !           116:     // Insert new item.
        !           117:     if (type != E820_HOLE)
        !           118:         insert_e820(i, start, size, type);
        !           119:     //dump_map();
        !           120: }
        !           121: 
        !           122: // Find highest area of 32bit memory that can hold the given size.
        !           123: struct e820entry *
        !           124: find_high_area(u32 size)
        !           125: {
        !           126:     int i;
        !           127:     for (i=e820_count-1; i>=0; i--) {
        !           128:         struct e820entry *e = &e820_list[i];
        !           129:         u64 end = e->start + e->size;
        !           130:         if (e->type != E820_RAM || end > 0xffffffff || e->size < size)
        !           131:             continue;
        !           132:         if (end < 1024*1024 + size)
        !           133:             break;
        !           134:         return e;
        !           135:     }
        !           136:     return NULL;
        !           137: }
        !           138: 
        !           139: // Prep for memmap stuff - init bios table locations.
        !           140: void
        !           141: memmap_setup()
        !           142: {
        !           143:     e820_count = 0;
        !           144: }
        !           145: 
        !           146: // Report on final memory locations.
        !           147: void
        !           148: memmap_finalize()
        !           149: {
        !           150:     dump_map();
        !           151: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.