Fixed buffer overflow in mserver; fixed type of checkinfo () 2nd parameter; memory
[ZeXOS.git] / kernel / core / mm / kzmem.c
blobaa9f37e27dc2291df06260afdb7235461743c925
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <system.h>
23 #include <arch/io.h>
24 #include <string.h>
25 #include <build.h>
26 #include <config.h>
27 #include <mutex.h>
29 #ifdef CONFIG_MEM_ZALLOC
31 #define KMEM_HEAP_ADDR 0x200000 // MEMORY HEAP is placed on 2MB address
32 #define KMEM_MALLOC_MAGIC 0xebc9 // MALLOC STRUCTURE signature
34 #define KMEM_MALLOC_STATE_FREE 0xaa // MEMORY is FREE at moment
35 #define KMEM_MALLOC_STATE_USED 0xcc // MEMORY is USED at moment
38 typedef struct {
39 unsigned magic : 16;
40 unsigned state : 8;
41 void *next;
42 } __attribute__ ((__packed__)) malloc_t;
44 typedef struct {
45 void *addr; /* heap structure is covered by own heap structure address */
46 void *first; /* first malloc structure */
47 void *last; /* last malloc structure - usefully for calculate memory usage */
48 void *curr; /* current malloc structure */
49 } __attribute__ ((__packed__)) heap_t;
52 heap_t *heap; /* heap structure of memory */
53 MUTEX_CREATE (mutex_malloc);
54 MUTEX_CREATE (mutex_free);
56 void *kmalloc (size_t size)
58 if (!size)
59 return 0;
61 mutex_lock (&mutex_malloc);
63 unsigned malloc_len = sizeof (malloc_t); /* check malloc structure size */
64 unsigned need_alloc = 0;
66 /* let's find new or free malloc structure in memory */
68 malloc_t *malloc = (malloc_t *) heap->first;
70 for (;;) {
71 malloc = (malloc_t *) malloc->next;
73 //DPRINT ("malloc: 0x%x\n", malloc);
75 if (!malloc) {
76 DPRINT (DBG_MM | DBG_KMEM, "!malloc");
77 need_alloc = 1;
78 break;
81 if (malloc->magic != KMEM_MALLOC_MAGIC) {
82 DPRINT (DBG_MM | DBG_KMEM, "malloc->magic != KMEM_MALLOC_MAGIC");
83 need_alloc = 1;
84 break;
87 if (malloc->state == KMEM_MALLOC_STATE_USED) { /* It's OK */
88 //DPRINT ("DBG_MM | DBG_KMEM, malloc->state == KMEM_MALLOC_STATE_USED");
89 //need_alloc = 1;
90 continue;
93 /* we've found FREE memory block, at moment it is not used */
94 if (malloc->state == KMEM_MALLOC_STATE_FREE) {
95 /* read next malloc structure, right behind free block */
96 malloc_t *next = (malloc_t *) malloc;
98 DPRINT (DBG_MM | DBG_KMEM, "malloc->state == KMEM_MALLOC_STATE_FREE");
100 while (1) {
101 //kprintf ("hhhe\n");
102 next = (malloc_t *) next->next;
104 if (next->magic != KMEM_MALLOC_MAGIC) {
105 DPRINT (DBG_MM | DBG_KMEM, "next->magic != KMEM_MALLOC_MAGIC");
106 need_alloc = 1;
107 break;
110 if (next->state == KMEM_MALLOC_STATE_USED)
111 break;
113 if (next->state != KMEM_MALLOC_STATE_FREE)
114 break;
117 if (need_alloc)
118 break;
120 unsigned diff = (unsigned) ((void *) next - (void *) malloc);
122 DPRINT (DBG_MM | DBG_KMEM, "diff: %d", diff);
124 if (diff < size)
125 continue;
127 break;
131 if (need_alloc) {
132 /* when old malloc structures are full, let's grab new block of memory */
133 malloc = heap->curr;
135 malloc->magic = KMEM_MALLOC_MAGIC;
137 malloc->next = (void *) ((void *) malloc + malloc_len + size);
140 malloc->state = KMEM_MALLOC_STATE_USED;
142 heap->curr = malloc->next;
144 /* save last malloc structure pointer to heap */
145 if ((unsigned) heap->curr > (unsigned) heap->last)
146 heap->last = heap->curr;
148 DPRINT (DBG_MM | DBG_KMEM, "malloc: 0x%x", malloc);
150 //kprintf ("kmalloc: 0x%x : %d\n", ((void *) malloc + malloc_len), size);
152 mutex_unlock (&mutex_malloc);
154 return (void *) ((void *) malloc + malloc_len);
157 void *krealloc (void *ptr, size_t size)
159 return 0;
162 void kfree (void *ptr)
164 if (!ptr)
165 return;
167 mutex_lock (&mutex_free);
169 /* we need find malloc structure - it could be risk working with lower memory address */
170 malloc_t *malloc = (void *) ((void *) ptr - sizeof (malloc_t));
172 /* check malloc signature, when not agree, ptr pointing to wrong memory address */
173 if (malloc->magic != KMEM_MALLOC_MAGIC) {
174 kprintf ("free: malloc->magic != KMEM_MALLOC_MAGIC\n");
175 return;
178 if (malloc->state == KMEM_MALLOC_STATE_FREE) {
179 kprintf ("kfree () - memory is FREE - double free !\n");
180 return;
183 if (malloc->state != KMEM_MALLOC_STATE_USED) {
184 kprintf ("malloc->state != KMEM_MALLOC_STATE_USED\n");
185 return;
188 /* match malloc as FREE */
189 malloc->state = KMEM_MALLOC_STATE_FREE;
191 mutex_unlock (&mutex_free);
194 unsigned kmem_init ()
196 heap = (heap_t *) KMEM_HEAP_ADDR;
198 /* we rather clear heap structure */
199 heap->addr = (void *) heap;
200 heap->first = (void *) ((void *) heap + sizeof (heap_t)); /* first malloc structure should be right behind heap structure */
201 heap->last = heap->first; /* last malloc structure - it is first at init */
202 heap->curr = heap->first; /* point to first malloc structure - well, it is clear and not used yet */
204 return 1;
208 unsigned short kmem_get ()
210 #ifdef ARCH_i386
211 register unsigned long *mem;
212 unsigned long mem_count, a, mem_end, bse_end;
213 unsigned short memkb;
214 unsigned char irq1, irq2;
215 unsigned long cr0;
217 /* save IRQ's */
218 irq1 = inb (0x21);
219 irq2 = inb (0xA1);
221 /* kill all irq's */
222 outb (0x21, 0xFF);
223 outb (0xA1, 0xFF);
225 mem_count = 0;
226 memkb = 0;
228 // store a copy of CR0
229 asm volatile ("movl %%cr0, %%eax;" : "=a"(cr0));
231 // invalidate the cache
232 // write-back and invalidate the cache
233 asm volatile ("wbinvd;");
235 // plug cr0 with just PE/CD/NW
236 // cache disable(486+), no-writeback(486+), 32bit mode(386+)
237 asm volatile ("movl %%eax, %%cr0;" ::
238 "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000));
240 do {
241 memkb ++;
242 mem_count += 1024*1024;
243 mem = (unsigned long *) mem_count;
245 a = *mem;
247 *mem = 0x55AA55AA;
249 /* the empty asm calls tell gcc not to rely on whats in its registers
250 as saved variables (this gets us around GCC optimisations) */
251 asm (";" ::: "memory");
252 if (*mem != 0x55AA55AA)
253 mem_count = 0;
254 else
256 *mem = 0xAA55AA55;
257 asm ("":::"memory");
258 if (*mem!=0xAA55AA55)
259 mem_count = 0;
262 asm (";":::"memory");
263 *mem = a;
264 } while (memkb < 4096 && mem_count != 0);
266 asm volatile ("movl %%eax, %%cr0;" :: "a" (cr0));
268 mem_end = memkb << 20;
269 mem = (unsigned long *) 0x413;
270 bse_end = ((*mem) &0xFFFF) << 6;
272 outb (0x21, irq1);
273 outb (0xA1, irq2);
275 return memkb;
276 #endif
277 return 0;
280 void util_cmdfree ()
282 unsigned used = (unsigned) heap->last - (unsigned) heap->first;
283 used /= 1024; // convert value to kB size
285 printf ("\ttotal\tused\tfree\tshared\tbuffers\tcached\n");
286 printf ("Mem: \t%u\t%u\t%u\t%u\t%u\t%u\n",
287 mem_ext * 1024, used, mem_ext * 1024 - used, 0, 0, 0);
290 /*****************************************************************************
291 *****************************************************************************/
292 unsigned int init_mm ()
294 if (!kmem_init ())
295 return 0;
297 //mem_ext = kmem_get (); // get extended memory (in Mb)
299 pmem_init ();
301 return 1;
304 #endif