+
+ start = boot_mem_map[i].start;
+ sz = boot_mem_map[i].size & 0xfffffffc;
+ end = start + sz;
+ if(end < sz) {
+ end = 0xfffffffc;
+ sz = end - start;
+ }
+
+ /* ignore any memory ranges which end before the end of the kernel image */
+ if(end < MEM_START) continue;
+ if(start < MEM_START) {
+ start = MEM_START;
+ }
+
+ add_memory(start, sz);
+ total += sz;
+
+ pg = ADDR_TO_PAGE(end);
+ if(max_pg < pg) {
+ max_pg = pg;
+ }
+ }
+
+ i = 0;
+ while(total > 1024) {
+ rem = total & 0x3ff;
+ total >>= 10;
+ ++i;
+ }
+ printf("Total usable RAM: %u.%u %s\n", total, 100 * rem / 1024, suffix[i]);
+
+ bmsize = max_pg / 8; /* size of the useful bitmap in bytes */
+
+ /* mark all pages occupied by the bitmap as usef */
+ used_end = (uint32_t)bitmap + bmsize - 1;
+
+ printf("marking pages up to %x (page: %d) as used\n", used_end, ADDR_TO_PAGE(used_end));
+
+ for(i=0; i<=used_end; i++) {
+ mark_page(i, USED);
+ }
+}
+
+/* alloc_phys_page finds the first available page of physical memory,
+ * marks it as used in the bitmap, and returns its number. If there's
+ * no unused physical page, -1 is returned.
+ */
+int alloc_ppage(void)
+{
+ int i, idx, max, intr_state;
+
+ intr_state = get_intr_flag();
+ disable_intr();
+
+ idx = last_alloc_idx;
+ max = bmsize / 4;
+
+ while(idx <= max) {
+ /* if at least one bit is 0 then we have at least
+ * one free page. find it and allocate it.
+ */
+ if(bitmap[idx] != 0xffffffff) {
+ for(i=0; i<32; i++) {
+ int pg = idx * 32 + i;
+
+ if(IS_FREE(pg)) {
+ mark_page(pg, USED);
+
+ last_alloc_idx = idx;
+
+ /*printf("alloc_phys_page() -> %x (page: %d)\n", PAGE_TO_ADDR(pg), pg);*/
+
+ set_intr_flag(intr_state);
+ return pg;
+ }
+ }
+ panic("can't happen: alloc_ppage (mem.c)\n");
+ }
+ idx++;
+ }
+
+ set_intr_flag(intr_state);
+ return -1;
+}
+
+/* free_ppage marks the physical page, free in the allocation bitmap.
+ *
+ * CAUTION: no checks are done that this page should actually be freed or not.
+ * If you call free_phys_page with the address of some part of memory that was
+ * originally reserved due to it being in a memory hole or part of the kernel
+ * image or whatever, it will be subsequently allocatable by alloc_phys_page.
+ */
+void free_ppage(int pg)
+{
+ int bmidx = BM_IDX(pg);
+
+ int intr_state = get_intr_flag();
+ disable_intr();
+
+ if(IS_FREE(pg)) {
+ panic("free_ppage(%d): I thought that was already free!\n", pg);
+ }
+
+ mark_page(pg, FREE);
+ if(bmidx < last_alloc_idx) {
+ last_alloc_idx = bmidx;
+ }
+
+ set_intr_flag(intr_state);
+}
+
+
+int alloc_ppage_range(int start, int size)
+{
+ int i, pg = start;
+
+ /* first validate that no page in the requested range is allocated */
+ for(i=0; i<size; i++) {
+ if(!IS_FREE(pg)) {
+ return -1;
+ }
+ ++pg;
+ }
+
+ /* all is well, mark them as used */
+ pg = start;
+ for(i=0; i<size; i++) {
+ mark_page(pg++, USED);
+ }
+ return 0;
+}
+
+int free_ppage_range(int start, int size)
+{
+ int i, pg = start;
+
+ for(i=0; i<size; i++) {
+ free_ppage(pg++);
+ }
+ return 0;
+}
+
+/* adds a range of physical memory to the available pool. used during init_mem
+ * when traversing the memory map.
+ */
+static void add_memory(uint32_t start, size_t sz)
+{
+ int i, szpg, pg;
+
+ szpg = ADDR_TO_PAGE(sz + 4095);
+ pg = ADDR_TO_PAGE(start);
+
+ for(i=0; i<szpg; i++) {
+ mark_page(pg++, FREE);