Annotation of qemu/roms/seabios/src/pmm.c, revision 1.1.1.3

1.1       root        1: // Post memory manager (PMM) calls
                      2: //
                      3: // Copyright (C) 2009  Kevin O'Connor <[email protected]>
                      4: //
                      5: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      6: 
                      7: #include "util.h" // checksum
                      8: #include "config.h" // BUILD_BIOS_ADDR
1.1.1.3 ! root        9: #include "memmap.h" // struct e820entry
1.1       root       10: #include "farptr.h" // GET_FARVAR
                     11: #include "biosvar.h" // GET_BDA
                     12: 
                     13: 
1.1.1.2   root       14: #if MODESEGMENT
1.1       root       15: // The 16bit pmm entry points runs in "big real" mode, and can
                     16: // therefore read/write to the 32bit malloc variables.
1.1.1.2   root       17: #define GET_PMMVAR(var) ({                      \
                     18:             SET_SEG(ES, 0);                     \
                     19:             __GET_VAR("addr32 ", ES, (var)); })
                     20: #define SET_PMMVAR(var, val) do {               \
                     21:         SET_SEG(ES, 0);                         \
                     22:         __SET_VAR("addr32 ", ES, (var), (val)); \
                     23:     } while (0)
1.1       root       24: #else
                     25: #define GET_PMMVAR(var) (var)
                     26: #define SET_PMMVAR(var, val) do { (var) = (val); } while (0)
                     27: #endif
                     28: 
1.1.1.3 ! root       29: // Information on a reserved area.
        !            30: struct allocinfo_s {
        !            31:     struct allocinfo_s *next, **pprev;
        !            32:     void *data, *dataend, *allocend;
        !            33: };
        !            34: 
        !            35: // Information on a tracked memory allocation.
        !            36: struct allocdetail_s {
        !            37:     struct allocinfo_s detailinfo;
        !            38:     struct allocinfo_s datainfo;
        !            39:     u32 handle;
        !            40: };
        !            41: 
        !            42: // The various memory zones.
1.1       root       43: struct zone_s {
1.1.1.3 ! root       44:     struct allocinfo_s *info;
1.1       root       45: };
                     46: 
1.1.1.3 ! root       47: struct zone_s ZoneLow VAR32FLATVISIBLE;
        !            48: struct zone_s ZoneHigh VAR32FLATVISIBLE;
1.1.1.2   root       49: struct zone_s ZoneFSeg VAR32FLATVISIBLE;
1.1.1.3 ! root       50: struct zone_s ZoneTmpLow VAR32FLATVISIBLE;
        !            51: struct zone_s ZoneTmpHigh VAR32FLATVISIBLE;
1.1       root       52: 
1.1.1.2   root       53: struct zone_s *Zones[] VAR32FLATVISIBLE = {
1.1       root       54:     &ZoneTmpLow, &ZoneLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh
                     55: };
                     56: 
                     57: 
                     58: /****************************************************************
1.1.1.3 ! root       59:  * low-level memory reservations
        !            60:  ****************************************************************/
        !            61: 
        !            62: // Find and reserve space from a given zone
        !            63: static void *
        !            64: allocSpace(struct zone_s *zone, u32 size, u32 align, struct allocinfo_s *fill)
        !            65: {
        !            66:     struct allocinfo_s *info;
        !            67:     for (info = GET_PMMVAR(zone->info); info; info = GET_PMMVAR(info->next)) {
        !            68:         void *dataend = GET_PMMVAR(info->dataend);
        !            69:         void *allocend = GET_PMMVAR(info->allocend);
        !            70:         void *newallocend = (void*)ALIGN_DOWN((u32)allocend - size, align);
        !            71:         if (newallocend >= dataend && newallocend <= allocend) {
        !            72:             // Found space - now reserve it.
        !            73:             struct allocinfo_s **pprev = GET_PMMVAR(info->pprev);
        !            74:             if (!fill)
        !            75:                 fill = newallocend;
        !            76:             SET_PMMVAR(fill->next, info);
        !            77:             SET_PMMVAR(fill->pprev, pprev);
        !            78:             SET_PMMVAR(fill->data, newallocend);
        !            79:             SET_PMMVAR(fill->dataend, newallocend + size);
        !            80:             SET_PMMVAR(fill->allocend, allocend);
        !            81: 
        !            82:             SET_PMMVAR(info->allocend, newallocend);
        !            83:             SET_PMMVAR(info->pprev, &fill->next);
        !            84:             SET_PMMVAR(*pprev, fill);
        !            85:             return newallocend;
        !            86:         }
        !            87:     }
        !            88:     return NULL;
        !            89: }
        !            90: 
        !            91: // Release space allocated with allocSpace()
        !            92: static void
        !            93: freeSpace(struct allocinfo_s *info)
        !            94: {
        !            95:     struct allocinfo_s *next = GET_PMMVAR(info->next);
        !            96:     struct allocinfo_s **pprev = GET_PMMVAR(info->pprev);
        !            97:     SET_PMMVAR(*pprev, next);
        !            98:     if (next) {
        !            99:         if (GET_PMMVAR(next->allocend) == GET_PMMVAR(info->data))
        !           100:             SET_PMMVAR(next->allocend, GET_PMMVAR(info->allocend));
        !           101:         SET_PMMVAR(next->pprev, pprev);
        !           102:     }
        !           103: }
        !           104: 
        !           105: // Add new memory to a zone
        !           106: static void
        !           107: addSpace(struct zone_s *zone, void *start, void *end)
        !           108: {
        !           109:     // Find position to add space
        !           110:     struct allocinfo_s **pprev = &zone->info, *info;
        !           111:     for (;;) {
        !           112:         info = GET_PMMVAR(*pprev);
        !           113:         if (!info || GET_PMMVAR(info->data) < start)
        !           114:             break;
        !           115:         pprev = &info->next;
        !           116:     }
        !           117: 
        !           118:     // Add space using temporary allocation info.
        !           119:     struct allocdetail_s tempdetail;
        !           120:     tempdetail.datainfo.next = info;
        !           121:     tempdetail.datainfo.pprev = pprev;
        !           122:     tempdetail.datainfo.data = tempdetail.datainfo.dataend = start;
        !           123:     tempdetail.datainfo.allocend = end;
        !           124:     struct allocdetail_s *tempdetailp = MAKE_FLATPTR(GET_SEG(SS), &tempdetail);
        !           125:     SET_PMMVAR(*pprev, &tempdetailp->datainfo);
        !           126:     if (info)
        !           127:         SET_PMMVAR(info->pprev, &tempdetailp->datainfo.next);
        !           128: 
        !           129:     // Allocate final allocation info.
        !           130:     struct allocdetail_s *detail = allocSpace(
        !           131:         &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL);
        !           132:     if (!detail) {
        !           133:         detail = allocSpace(&ZoneTmpLow, sizeof(*detail)
        !           134:                             , MALLOC_MIN_ALIGN, NULL);
        !           135:         if (!detail) {
        !           136:             SET_PMMVAR(*tempdetail.datainfo.pprev, tempdetail.datainfo.next);
        !           137:             if (tempdetail.datainfo.next)
        !           138:                 SET_PMMVAR(tempdetail.datainfo.next->pprev
        !           139:                            , tempdetail.datainfo.pprev);
        !           140:             warn_noalloc();
        !           141:             return;
        !           142:         }
        !           143:     }
        !           144: 
        !           145:     // Replace temp alloc space with final alloc space
        !           146:     memcpy_fl(&detail->datainfo, &tempdetailp->datainfo
        !           147:               , sizeof(detail->datainfo));
        !           148:     SET_PMMVAR(detail->handle, PMM_DEFAULT_HANDLE);
        !           149: 
        !           150:     SET_PMMVAR(*tempdetail.datainfo.pprev, &detail->datainfo);
        !           151:     if (tempdetail.datainfo.next)
        !           152:         SET_PMMVAR(tempdetail.datainfo.next->pprev, &detail->datainfo.next);
        !           153: }
        !           154: 
        !           155: // Search all zones for an allocation obtained from allocSpace()
        !           156: static struct allocinfo_s *
        !           157: findAlloc(void *data)
        !           158: {
        !           159:     int i;
        !           160:     for (i=0; i<ARRAY_SIZE(Zones); i++) {
        !           161:         struct zone_s *zone = GET_PMMVAR(Zones[i]);
        !           162:         struct allocinfo_s *info;
        !           163:         for (info = GET_PMMVAR(zone->info); info; info = GET_PMMVAR(info->next))
        !           164:             if (GET_PMMVAR(info->data) == data)
        !           165:                 return info;
        !           166:     }
        !           167:     return NULL;
        !           168: }
        !           169: 
        !           170: // Return the last sentinal node of a zone
        !           171: static struct allocinfo_s *
        !           172: findLast(struct zone_s *zone)
        !           173: {
        !           174:     struct allocinfo_s *info = GET_PMMVAR(zone->info);
        !           175:     if (!info)
        !           176:         return NULL;
        !           177:     for (;;) {
        !           178:         struct allocinfo_s *next = GET_PMMVAR(info->next);
        !           179:         if (!next)
        !           180:             return info;
        !           181:         info = next;
        !           182:     }
        !           183: }
        !           184: 
        !           185: 
        !           186: /****************************************************************
        !           187:  * Setup
        !           188:  ****************************************************************/
        !           189: 
        !           190: void
        !           191: malloc_setup(void)
        !           192: {
        !           193:     ASSERT32FLAT();
        !           194:     dprintf(3, "malloc setup\n");
        !           195: 
        !           196:     ZoneLow.info = ZoneHigh.info = ZoneFSeg.info = NULL;
        !           197:     ZoneTmpLow.info = ZoneTmpHigh.info = NULL;
        !           198: 
        !           199:     // Clear memory in 0xf0000 area.
        !           200:     extern u8 code32flat_start[];
        !           201:     if ((u32)code32flat_start > BUILD_BIOS_ADDR)
        !           202:         // Clear unused parts of f-segment
        !           203:         memset((void*)BUILD_BIOS_ADDR, 0
        !           204:                , (u32)code32flat_start - BUILD_BIOS_ADDR);
        !           205:     memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE);
        !           206: 
        !           207:     // Populate temp high ram
        !           208:     u32 highram = 0;
        !           209:     int i;
        !           210:     for (i=e820_count-1; i>=0; i--) {
        !           211:         struct e820entry *en = &e820_list[i];
        !           212:         u64 end = en->start + en->size;
        !           213:         if (end < 1024*1024)
        !           214:             break;
        !           215:         if (en->type != E820_RAM || end > 0xffffffff)
        !           216:             continue;
        !           217:         u32 s = en->start, e = end;
        !           218:         if (!highram) {
        !           219:             u32 newe = ALIGN_DOWN(e - CONFIG_MAX_HIGHTABLE, MALLOC_MIN_ALIGN);
        !           220:             if (newe <= e && newe >= s) {
        !           221:                 highram = newe;
        !           222:                 e = newe;
        !           223:             }
        !           224:         }
        !           225:         addSpace(&ZoneTmpHigh, (void*)s, (void*)e);
        !           226:     }
        !           227: 
        !           228:     // Populate other regions
        !           229:     addSpace(&ZoneTmpLow, (void*)BUILD_STACK_ADDR, (void*)BUILD_EBDA_MINIMUM);
        !           230:     addSpace(&ZoneFSeg, BiosTableSpace, &BiosTableSpace[CONFIG_MAX_BIOSTABLE]);
        !           231:     addSpace(&ZoneLow, (void*)BUILD_LOWRAM_END, (void*)BUILD_LOWRAM_END);
        !           232:     if (highram) {
        !           233:         addSpace(&ZoneHigh, (void*)highram
        !           234:                  , (void*)highram + CONFIG_MAX_HIGHTABLE);
        !           235:         add_e820(highram, CONFIG_MAX_HIGHTABLE, E820_RESERVED);
        !           236:     }
        !           237: }
        !           238: 
        !           239: void
        !           240: malloc_finalize(void)
        !           241: {
        !           242:     dprintf(3, "malloc finalize\n");
        !           243: 
        !           244:     // Reserve more low-mem if needed.
        !           245:     u32 endlow = GET_BDA(mem_size_kb)*1024;
        !           246:     add_e820(endlow, BUILD_LOWRAM_END-endlow, E820_RESERVED);
        !           247: 
        !           248:     // Give back unused high ram.
        !           249:     struct allocinfo_s *info = findLast(&ZoneHigh);
        !           250:     if (info) {
        !           251:         u32 giveback = ALIGN_DOWN(info->allocend - info->dataend, PAGE_SIZE);
        !           252:         add_e820((u32)info->dataend, giveback, E820_RAM);
        !           253:         dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback);
        !           254:     }
        !           255: 
        !           256:     // Clear low-memory allocations.
        !           257:     memset((void*)BUILD_STACK_ADDR, 0, BUILD_EBDA_MINIMUM - BUILD_STACK_ADDR);
        !           258: }
        !           259: 
        !           260: 
        !           261: /****************************************************************
1.1       root      262:  * ebda movement
                    263:  ****************************************************************/
                    264: 
                    265: // Move ebda
                    266: static int
                    267: relocate_ebda(u32 newebda, u32 oldebda, u8 ebda_size)
                    268: {
                    269:     u32 lowram = GET_BDA(mem_size_kb) * 1024;
                    270:     if (oldebda != lowram)
                    271:         // EBDA isn't at end of ram - give up.
                    272:         return -1;
                    273: 
1.1.1.3 ! root      274:     // Do copy (this assumes memcpy copies forward - otherwise memmove
        !           275:     // is needed)
        !           276:     memcpy_fl((void*)newebda, (void*)oldebda, ebda_size * 1024);
1.1       root      277: 
                    278:     // Update indexes
                    279:     dprintf(1, "ebda moved from %x to %x\n", oldebda, newebda);
                    280:     SET_BDA(mem_size_kb, newebda / 1024);
                    281:     SET_BDA(ebda_seg, FLATPTR_TO_SEG(newebda));
                    282:     return 0;
                    283: }
                    284: 
                    285: // Support expanding the ZoneLow dynamically.
                    286: static void
                    287: zonelow_expand(u32 size, u32 align)
                    288: {
1.1.1.3 ! root      289:     struct allocinfo_s *info = findLast(&ZoneLow);
        !           290:     if (!info)
        !           291:         return;
        !           292:     u32 oldpos = (u32)GET_PMMVAR(info->allocend);
1.1       root      293:     u32 newpos = ALIGN_DOWN(oldpos - size, align);
1.1.1.3 ! root      294:     u32 bottom = (u32)GET_PMMVAR(info->dataend);
1.1       root      295:     if (newpos >= bottom && newpos <= oldpos)
                    296:         // Space already present.
                    297:         return;
                    298:     u16 ebda_seg = get_ebda_seg();
                    299:     u32 ebda_pos = (u32)MAKE_FLATPTR(ebda_seg, 0);
                    300:     u8 ebda_size = GET_EBDA2(ebda_seg, size);
                    301:     u32 ebda_end = ebda_pos + ebda_size * 1024;
1.1.1.3 ! root      302:     if (ebda_end != bottom)
1.1       root      303:         // Something else is after ebda - can't use any existing space.
1.1.1.3 ! root      304:         newpos = ALIGN_DOWN(ebda_end - size, align);
1.1       root      305:     u32 newbottom = ALIGN_DOWN(newpos, 1024);
                    306:     u32 newebda = ALIGN_DOWN(newbottom - ebda_size * 1024, 1024);
                    307:     if (newebda < BUILD_EBDA_MINIMUM)
                    308:         // Not enough space.
                    309:         return;
                    310: 
                    311:     // Move ebda
                    312:     int ret = relocate_ebda(newebda, ebda_pos, ebda_size);
                    313:     if (ret)
                    314:         return;
                    315: 
                    316:     // Update zone
1.1.1.3 ! root      317:     if (ebda_end == bottom) {
        !           318:         SET_PMMVAR(info->data, (void*)newbottom);
        !           319:         SET_PMMVAR(info->dataend, (void*)newbottom);
        !           320:     } else
        !           321:         addSpace(&ZoneLow, (void*)newbottom, (void*)ebda_end);
1.1       root      322: }
                    323: 
1.1.1.3 ! root      324: // Check if can expand the given zone to fulfill an allocation
1.1       root      325: static void *
1.1.1.3 ! root      326: allocExpandSpace(struct zone_s *zone, u32 size, u32 align
        !           327:                  , struct allocinfo_s *fill)
1.1       root      328: {
1.1.1.3 ! root      329:     void *data = allocSpace(zone, size, align, fill);
        !           330:     if (data || zone != &ZoneLow)
        !           331:         return data;
        !           332: 
        !           333:     // Make sure to not move ebda while an optionrom is running.
        !           334:     if (unlikely(wait_preempt())) {
        !           335:         data = allocSpace(zone, size, align, fill);
        !           336:         if (data)
        !           337:             return data;
1.1       root      338:     }
                    339: 
1.1.1.3 ! root      340:     zonelow_expand(size, align);
        !           341:     return allocSpace(zone, size, align, fill);
1.1       root      342: }
                    343: 
                    344: 
                    345: /****************************************************************
                    346:  * tracked memory allocations
                    347:  ****************************************************************/
                    348: 
                    349: // Allocate memory from the given zone and track it as a PMM allocation
1.1.1.3 ! root      350: void * __malloc
1.1       root      351: pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align)
                    352: {
1.1.1.3 ! root      353:     if (!size)
        !           354:         return NULL;
        !           355: 
        !           356:     // Find and reserve space for bookkeeping.
        !           357:     struct allocdetail_s *detail = allocSpace(
        !           358:         &ZoneTmpHigh, sizeof(*detail), MALLOC_MIN_ALIGN, NULL);
        !           359:     if (!detail) {
        !           360:         detail = allocSpace(&ZoneTmpLow, sizeof(*detail)
        !           361:                             , MALLOC_MIN_ALIGN, NULL);
        !           362:         if (!detail)
1.1       root      363:             return NULL;
                    364:     }
1.1.1.3 ! root      365: 
        !           366:     // Find and reserve space for main allocation
        !           367:     void *data = allocExpandSpace(zone, size, align, &detail->datainfo);
        !           368:     if (!data) {
        !           369:         freeSpace(&detail->detailinfo);
1.1       root      370:         return NULL;
                    371:     }
1.1.1.3 ! root      372: 
1.1       root      373:     dprintf(8, "pmm_malloc zone=%p handle=%x size=%d align=%x"
1.1.1.3 ! root      374:             " ret=%p (detail=%p)\n"
1.1       root      375:             , zone, handle, size, align
1.1.1.3 ! root      376:             , data, detail);
        !           377:     SET_PMMVAR(detail->handle, handle);
1.1       root      378: 
1.1.1.3 ! root      379:     return data;
1.1       root      380: }
                    381: 
                    382: // Free a data block allocated with pmm_malloc
                    383: int
                    384: pmm_free(void *data)
                    385: {
1.1.1.3 ! root      386:     struct allocinfo_s *info = findAlloc(data);
        !           387:     if (!info || data == (void*)info || data == GET_PMMVAR(info->dataend))
        !           388:         return -1;
        !           389:     struct allocdetail_s *detail = container_of(
        !           390:         info, struct allocdetail_s, datainfo);
        !           391:     dprintf(8, "pmm_free %p (detail=%p)\n", data, detail);
        !           392:     freeSpace(info);
        !           393:     freeSpace(&detail->detailinfo);
        !           394:     return 0;
1.1       root      395: }
                    396: 
                    397: // Find the amount of free space in a given zone.
                    398: static u32
                    399: pmm_getspace(struct zone_s *zone)
                    400: {
                    401:     // XXX - doesn't account for ZoneLow being able to grow.
1.1.1.3 ! root      402:     // XXX - results not reliable when CONFIG_THREAD_OPTIONROMS
        !           403:     u32 maxspace = 0;
        !           404:     struct allocinfo_s *info;
        !           405:     for (info = GET_PMMVAR(zone->info); info; info = GET_PMMVAR(info->next)) {
        !           406:         u32 space = GET_PMMVAR(info->allocend) - GET_PMMVAR(info->dataend);
        !           407:         if (space > maxspace)
        !           408:             maxspace = space;
        !           409:     }
        !           410: 
1.1       root      411:     if (zone != &ZoneTmpHigh && zone != &ZoneTmpLow)
1.1.1.3 ! root      412:         return maxspace;
1.1       root      413:     // Account for space needed for PMM tracking.
1.1.1.3 ! root      414:     u32 reserve = ALIGN(sizeof(struct allocdetail_s), MALLOC_MIN_ALIGN);
        !           415:     if (maxspace <= reserve)
1.1       root      416:         return 0;
1.1.1.3 ! root      417:     return maxspace - reserve;
1.1       root      418: }
                    419: 
                    420: // Find the data block allocated with pmm_malloc with a given handle.
                    421: static void *
                    422: pmm_find(u32 handle)
                    423: {
1.1.1.3 ! root      424:     int i;
        !           425:     for (i=0; i<ARRAY_SIZE(Zones); i++) {
        !           426:         struct zone_s *zone = GET_PMMVAR(Zones[i]);
        !           427:         struct allocinfo_s *info;
        !           428:         for (info = GET_PMMVAR(zone->info); info
        !           429:                  ; info = GET_PMMVAR(info->next)) {
        !           430:             if (GET_PMMVAR(info->data) != (void*)info)
        !           431:                 continue;
        !           432:             struct allocdetail_s *detail = container_of(
        !           433:                 info, struct allocdetail_s, detailinfo);
        !           434:             if (GET_PMMVAR(detail->handle) == handle)
        !           435:                 return GET_PMMVAR(detail->datainfo.data);
        !           436:         }
1.1       root      437:     }
1.1.1.3 ! root      438:     return NULL;
1.1       root      439: }
                    440: 
                    441: 
                    442: /****************************************************************
                    443:  * pmm interface
                    444:  ****************************************************************/
                    445: 
                    446: struct pmmheader {
                    447:     u32 signature;
                    448:     u8 version;
                    449:     u8 length;
                    450:     u8 checksum;
                    451:     u16 entry_offset;
                    452:     u16 entry_seg;
                    453:     u8 reserved[5];
                    454: } PACKED;
                    455: 
                    456: extern struct pmmheader PMMHEADER;
                    457: 
                    458: #define PMM_SIGNATURE 0x4d4d5024 // $PMM
                    459: 
                    460: #if CONFIG_PMM
                    461: struct pmmheader PMMHEADER __aligned(16) VAR16EXPORT = {
                    462:     .version = 0x01,
                    463:     .length = sizeof(PMMHEADER),
                    464:     .entry_seg = SEG_BIOS,
                    465: };
                    466: #endif
                    467: 
                    468: #define PMM_FUNCTION_NOT_SUPPORTED 0xffffffff
                    469: 
                    470: // PMM - allocate
                    471: static u32
                    472: handle_pmm00(u16 *args)
                    473: {
                    474:     u32 length = *(u32*)&args[1], handle = *(u32*)&args[3];
                    475:     u16 flags = args[5];
                    476:     dprintf(3, "pmm00: length=%x handle=%x flags=%x\n"
                    477:             , length, handle, flags);
                    478:     struct zone_s *lowzone = &ZoneTmpLow, *highzone = &ZoneTmpHigh;
                    479:     if (flags & 8) {
                    480:         // Permanent memory request.
                    481:         lowzone = &ZoneLow;
                    482:         highzone = &ZoneHigh;
                    483:     }
                    484:     if (!length) {
                    485:         // Memory size request
                    486:         switch (flags & 3) {
                    487:         default:
                    488:         case 0:
                    489:             return 0;
                    490:         case 1:
                    491:             return pmm_getspace(lowzone);
                    492:         case 2:
                    493:             return pmm_getspace(highzone);
                    494:         case 3: {
                    495:             u32 spacelow = pmm_getspace(lowzone);
                    496:             u32 spacehigh = pmm_getspace(highzone);
                    497:             if (spacelow > spacehigh)
                    498:                 return spacelow;
                    499:             return spacehigh;
                    500:         }
                    501:         }
                    502:     }
                    503:     u32 size = length * 16;
                    504:     if ((s32)size <= 0)
                    505:         return 0;
                    506:     u32 align = MALLOC_MIN_ALIGN;
                    507:     if (flags & 4) {
                    508:         align = 1<<__ffs(size);
                    509:         if (align < MALLOC_MIN_ALIGN)
                    510:             align = MALLOC_MIN_ALIGN;
                    511:     }
                    512:     switch (flags & 3) {
                    513:     default:
                    514:     case 0:
                    515:         return 0;
                    516:     case 1:
                    517:         return (u32)pmm_malloc(lowzone, handle, size, align);
                    518:     case 2:
                    519:         return (u32)pmm_malloc(highzone, handle, size, align);
                    520:     case 3: {
                    521:         void *data = pmm_malloc(lowzone, handle, size, align);
                    522:         if (data)
                    523:             return (u32)data;
                    524:         return (u32)pmm_malloc(highzone, handle, size, align);
                    525:     }
                    526:     }
                    527: }
                    528: 
                    529: // PMM - find
                    530: static u32
                    531: handle_pmm01(u16 *args)
                    532: {
                    533:     u32 handle = *(u32*)&args[1];
                    534:     dprintf(3, "pmm01: handle=%x\n", handle);
                    535:     if (handle == PMM_DEFAULT_HANDLE)
                    536:         return 0;
                    537:     return (u32)pmm_find(handle);
                    538: }
                    539: 
                    540: // PMM - deallocate
                    541: static u32
                    542: handle_pmm02(u16 *args)
                    543: {
                    544:     u32 buffer = *(u32*)&args[1];
                    545:     dprintf(3, "pmm02: buffer=%x\n", buffer);
                    546:     int ret = pmm_free((void*)buffer);
                    547:     if (ret)
                    548:         // Error
                    549:         return 1;
                    550:     return 0;
                    551: }
                    552: 
                    553: static u32
                    554: handle_pmmXX(u16 *args)
                    555: {
                    556:     return PMM_FUNCTION_NOT_SUPPORTED;
                    557: }
                    558: 
                    559: u32 VISIBLE16
                    560: handle_pmm(u16 *args)
                    561: {
                    562:     if (! CONFIG_PMM)
                    563:         return PMM_FUNCTION_NOT_SUPPORTED;
                    564: 
                    565:     u16 arg1 = args[0];
                    566:     dprintf(DEBUG_HDL_pmm, "pmm call arg1=%x\n", arg1);
                    567: 
                    568:     switch (arg1) {
                    569:     case 0x00: return handle_pmm00(args);
                    570:     case 0x01: return handle_pmm01(args);
                    571:     case 0x02: return handle_pmm02(args);
                    572:     default:   return handle_pmmXX(args);
                    573:     }
                    574: }
                    575: 
                    576: // romlayout.S
1.1.1.2   root      577: extern void entry_pmm(void);
1.1       root      578: 
                    579: void
1.1.1.2   root      580: pmm_setup(void)
1.1       root      581: {
                    582:     if (! CONFIG_PMM)
                    583:         return;
                    584: 
                    585:     dprintf(3, "init PMM\n");
                    586: 
                    587:     PMMHEADER.signature = PMM_SIGNATURE;
                    588:     PMMHEADER.entry_offset = (u32)entry_pmm - BUILD_BIOS_ADDR;
                    589:     PMMHEADER.checksum -= checksum(&PMMHEADER, sizeof(PMMHEADER));
                    590: }
                    591: 
                    592: void
1.1.1.2   root      593: pmm_finalize(void)
1.1       root      594: {
                    595:     if (! CONFIG_PMM)
                    596:         return;
                    597: 
                    598:     dprintf(3, "finalize PMM\n");
                    599: 
                    600:     PMMHEADER.signature = 0;
                    601:     PMMHEADER.entry_offset = 0;
                    602: }

unix.superglobalmegacorp.com

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