blob: 6403414724867a733a2dea61d9dca3ee9d3067cf [file] [log] [blame]
Kevin O'Connore54ee382009-07-26 19:33:13 -04001// Post memory manager (PMM) calls
2//
Kevin O'Connor9dea5902013-09-14 20:23:54 -04003// Copyright (C) 2009-2013 Kevin O'Connor <kevin@koconnor.net>
Kevin O'Connore54ee382009-07-26 19:33:13 -04004//
5// This file may be distributed under the terms of the GNU LGPLv3 license.
6
Kevin O'Connor9dea5902013-09-14 20:23:54 -04007#include "biosvar.h" // FUNC16
8#include "config.h" // CONFIG_*
Kevin O'Connor9dea5902013-09-14 20:23:54 -04009#include "malloc.h" // _malloc
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040010#include "output.h" // dprintf
Kevin O'Connorb18557a2013-09-14 23:09:06 -040011#include "std/pmm.h" // PMM_SIGNATURE
Kevin O'Connor9dea5902013-09-14 20:23:54 -040012#include "string.h" // checksum
Kevin O'Connor2d2fa312013-09-14 21:55:26 -040013#include "util.h" // pmm_init
Kevin O'Connorb9c6a962013-09-14 13:01:30 -040014#include "x86.h" // __ffs
Kevin O'Connor0bf92702009-08-01 11:45:37 -040015
Kevin O'Connore54ee382009-07-26 19:33:13 -040016extern struct pmmheader PMMHEADER;
17
Kevin O'Connore54ee382009-07-26 19:33:13 -040018#if CONFIG_PMM
Kevin O'Connor89a2f962013-02-18 23:36:03 -050019struct pmmheader PMMHEADER __aligned(16) VARFSEG = {
Kevin O'Connor6156afe2013-01-20 10:43:54 -050020 .signature = PMM_SIGNATURE,
Kevin O'Connore54ee382009-07-26 19:33:13 -040021 .version = 0x01,
22 .length = sizeof(PMMHEADER),
Kevin O'Connore54ee382009-07-26 19:33:13 -040023};
24#endif
25
Kevin O'Connore54ee382009-07-26 19:33:13 -040026// PMM - allocate
27static u32
28handle_pmm00(u16 *args)
29{
30 u32 length = *(u32*)&args[1], handle = *(u32*)&args[3];
31 u16 flags = args[5];
Kevin O'Connor0bf92702009-08-01 11:45:37 -040032 dprintf(3, "pmm00: length=%x handle=%x flags=%x\n"
Kevin O'Connore54ee382009-07-26 19:33:13 -040033 , length, handle, flags);
Kevin O'Connor0e9fd612009-08-22 21:31:58 -040034 struct zone_s *lowzone = &ZoneTmpLow, *highzone = &ZoneTmpHigh;
35 if (flags & 8) {
36 // Permanent memory request.
37 lowzone = &ZoneLow;
38 highzone = &ZoneHigh;
39 }
Kevin O'Connor0bf92702009-08-01 11:45:37 -040040 if (!length) {
41 // Memory size request
42 switch (flags & 3) {
43 default:
44 case 0:
45 return 0;
46 case 1:
Kevin O'Connor9dea5902013-09-14 20:23:54 -040047 return malloc_getspace(lowzone);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040048 case 2:
Kevin O'Connor9dea5902013-09-14 20:23:54 -040049 return malloc_getspace(highzone);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040050 case 3: {
Kevin O'Connor9dea5902013-09-14 20:23:54 -040051 u32 spacelow = malloc_getspace(lowzone);
52 u32 spacehigh = malloc_getspace(highzone);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040053 if (spacelow > spacehigh)
54 return spacelow;
55 return spacehigh;
56 }
57 }
58 }
59 u32 size = length * 16;
60 if ((s32)size <= 0)
61 return 0;
62 u32 align = MALLOC_MIN_ALIGN;
63 if (flags & 4) {
64 align = 1<<__ffs(size);
65 if (align < MALLOC_MIN_ALIGN)
66 align = MALLOC_MIN_ALIGN;
67 }
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040068 u32 data;
Kevin O'Connor0bf92702009-08-01 11:45:37 -040069 switch (flags & 3) {
70 default:
71 case 0:
72 return 0;
73 case 1:
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040074 data = malloc_palloc(lowzone, size, align);
Kevin O'Connor743c1572013-12-14 13:14:02 -050075 break;
Kevin O'Connor0bf92702009-08-01 11:45:37 -040076 case 2:
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040077 data = malloc_palloc(highzone, size, align);
Kevin O'Connor743c1572013-12-14 13:14:02 -050078 break;
Kevin O'Connor0bf92702009-08-01 11:45:37 -040079 case 3: {
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040080 data = malloc_palloc(lowzone, size, align);
Kevin O'Connor743c1572013-12-14 13:14:02 -050081 if (!data)
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040082 data = malloc_palloc(highzone, size, align);
Kevin O'Connor0bf92702009-08-01 11:45:37 -040083 }
84 }
Kevin O'Connor743c1572013-12-14 13:14:02 -050085 if (data && handle != MALLOC_DEFAULT_HANDLE)
86 malloc_sethandle(data, handle);
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040087 return data;
Kevin O'Connore54ee382009-07-26 19:33:13 -040088}
89
90// PMM - find
91static u32
92handle_pmm01(u16 *args)
93{
94 u32 handle = *(u32*)&args[1];
Kevin O'Connor0bf92702009-08-01 11:45:37 -040095 dprintf(3, "pmm01: handle=%x\n", handle);
Kevin O'Connor9dea5902013-09-14 20:23:54 -040096 if (handle == MALLOC_DEFAULT_HANDLE)
Kevin O'Connor0bf92702009-08-01 11:45:37 -040097 return 0;
Kevin O'Connorfe6682d2015-09-22 14:45:25 -040098 return malloc_findhandle(handle);
Kevin O'Connore54ee382009-07-26 19:33:13 -040099}
100
101// PMM - deallocate
102static u32
103handle_pmm02(u16 *args)
104{
105 u32 buffer = *(u32*)&args[1];
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400106 dprintf(3, "pmm02: buffer=%x\n", buffer);
Kevin O'Connorfe6682d2015-09-22 14:45:25 -0400107 int ret = malloc_pfree(buffer);
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400108 if (ret)
109 // Error
110 return 1;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400111 return 0;
112}
113
114static u32
115handle_pmmXX(u16 *args)
116{
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400117 return PMM_FUNCTION_NOT_SUPPORTED;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400118}
119
Kevin O'Connor533b6282011-07-16 13:13:12 -0400120u32 VISIBLE32INIT
Kevin O'Connore54ee382009-07-26 19:33:13 -0400121handle_pmm(u16 *args)
122{
Kevin O'Connor1313b782011-07-16 13:39:26 -0400123 ASSERT32FLAT();
Kevin O'Connore54ee382009-07-26 19:33:13 -0400124 if (! CONFIG_PMM)
Kevin O'Connor0bf92702009-08-01 11:45:37 -0400125 return PMM_FUNCTION_NOT_SUPPORTED;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400126
127 u16 arg1 = args[0];
128 dprintf(DEBUG_HDL_pmm, "pmm call arg1=%x\n", arg1);
129
Kevin O'Connor533b6282011-07-16 13:13:12 -0400130 u32 ret;
131 switch (arg1) {
132 case 0x00: ret = handle_pmm00(args); break;
133 case 0x01: ret = handle_pmm01(args); break;
134 case 0x02: ret = handle_pmm02(args); break;
135 default: ret = handle_pmmXX(args); break;
136 }
137
Kevin O'Connor533b6282011-07-16 13:13:12 -0400138 return ret;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400139}
140
Kevin O'Connore54ee382009-07-26 19:33:13 -0400141void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500142pmm_init(void)
Kevin O'Connore54ee382009-07-26 19:33:13 -0400143{
144 if (! CONFIG_PMM)
145 return;
146
147 dprintf(3, "init PMM\n");
148
Kevin O'Connor6156afe2013-01-20 10:43:54 -0500149 PMMHEADER.entry = FUNC16(entry_pmm);
Kevin O'Connore54ee382009-07-26 19:33:13 -0400150 PMMHEADER.checksum -= checksum(&PMMHEADER, sizeof(PMMHEADER));
151}
152
153void
Kevin O'Connord83c87b2013-01-21 01:14:12 -0500154pmm_prepboot(void)
Kevin O'Connore54ee382009-07-26 19:33:13 -0400155{
156 if (! CONFIG_PMM)
157 return;
158
159 dprintf(3, "finalize PMM\n");
160
161 PMMHEADER.signature = 0;
Kevin O'Connor6156afe2013-01-20 10:43:54 -0500162 PMMHEADER.entry.segoff = 0;
Kevin O'Connore54ee382009-07-26 19:33:13 -0400163}