📄 boot_of.c
字号:
if (size_cells == 2 && (r < l) ) size = (size << 32) | a[r++]; end = ALIGN_DOWN(start + size, PAGE_SIZE); start = ALIGN_UP(start, PAGE_SIZE); DBG("%s: marking 0x%x - 0x%lx\n", __func__, pg << PAGE_SHIFT, start); start >>= PAGE_SHIFT; while (pg < MEM_AVAILABLE_PAGES && pg < start) { set_bit(pg, mem_available_pages); pg++; } pg = end >> PAGE_SHIFT; } } /* Now make sure we mark our own memory */ pg = (ulong)_start >> PAGE_SHIFT; start = (ulong)_end >> PAGE_SHIFT; DBG("%s: marking 0x%x - 0x%lx\n", __func__, pg << PAGE_SHIFT, start << PAGE_SHIFT); /* Lets try and detect if our image has stepped on something. It * is possible that FW has already subtracted our image from * available memory so we must make sure that the previous bits * are the same for the whole image */ tst = test_and_set_bit(pg, mem_available_pages); ++pg; while (pg <= start) { if (test_and_set_bit(pg, mem_available_pages) != tst) of_panic("%s: pg :0x%x of our image is different\n", __func__, pg); ++pg; } DBG("%s: marking 0x%x - 0x%x\n", __func__, 0 << PAGE_SHIFT, 3 << PAGE_SHIFT); /* First for pages (where the vectors are) should be left alone as well */ set_bit(0, mem_available_pages); set_bit(1, mem_available_pages); set_bit(2, mem_available_pages); set_bit(3, mem_available_pages);}#ifdef BOOT_OF_FREE/* this is here in case we ever need a free call at a later date */static void boot_of_free(ulong addr, ulong size){ ulong bits; ulong pos; ulong i; size = ALIGN_UP(size, PAGE_SIZE); bits = size >> PAGE_SHIFT; pos = addr >> PAGE_SHIFT; for (i = 0; i < bits; i++) { if (!test_and_clear_bit(pos + i, mem_available_pages)) of_panic("%s: pg :0x%lx was never allocated\n", __func__, pos + i); }}#endifstatic ulong boot_of_alloc(ulong size){ ulong bits; ulong pos; if (size == 0) return 0; DBG("%s(0x%lx)\n", __func__, size); size = ALIGN_UP(size, PAGE_SIZE); bits = size >> PAGE_SHIFT; pos = 0; for (;;) { ulong i; pos = find_next_zero_bit(mem_available_pages, MEM_AVAILABLE_PAGES, pos); DBG("%s: found start bit at: 0x%lx\n", __func__, pos); /* found nothing */ if ((pos + bits) > MEM_AVAILABLE_PAGES) { of_printf("%s: allocation of size: 0x%lx failed\n", __func__, size); return 0; } /* find a set that fits */ DBG("%s: checking for 0x%lx bits: 0x%lx\n", __func__, bits, pos); i = find_next_bit(mem_available_pages, MEM_AVAILABLE_PAGES, pos); if (i - pos >= bits) { uint addr = pos << PAGE_SHIFT; /* make sure OF is happy with our choice */ if (of_claim(addr, size, 0) != OF_FAILURE) { for (i = 0; i < bits; i++) set_bit(pos + i, mem_available_pages); DBG("%s: 0x%lx is good returning 0x%x\n", __func__, pos, addr); return addr; } /* if OF did not like the address then simply start from * the next bit */ i = 1; } pos = pos + i; }}int boot_of_mem_avail(int pos, ulong *startpage, ulong *endpage){ ulong freebit; ulong usedbit; if (pos >= MEM_AVAILABLE_PAGES) /* Stop iterating. */ return -1; /* Find first free page. */ freebit = find_next_zero_bit(mem_available_pages, MEM_AVAILABLE_PAGES, pos); if (freebit >= MEM_AVAILABLE_PAGES) { /* We know everything after MEM_AVAILABLE_PAGES is still free. */ *startpage = MEM_AVAILABLE_PAGES << PAGE_SHIFT; *endpage = ~0UL; return freebit; } *startpage = freebit << PAGE_SHIFT; /* Now find first used page after that. */ usedbit = find_next_bit(mem_available_pages, MEM_AVAILABLE_PAGES, freebit); if (usedbit >= MEM_AVAILABLE_PAGES) { /* We know everything after MEM_AVAILABLE_PAGES is still free. */ *endpage = ~0UL; return usedbit; } *endpage = usedbit << PAGE_SHIFT; return usedbit;}static ulong boot_of_mem_init(void){ int root; int p; int rc; uint addr_cells; uint size_cells; root = of_finddevice("/"); p = of_getchild(root); /* code is writen to assume sizes of 1 */ of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells)); of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells)); DBG("%s: address_cells=%d size_cells=%d\n", __func__, addr_cells, size_cells); /* We do ream memory discovery later, for now we only want to find * the first LMB */ do { const char memory[] = "memory"; char type[32]; type[0] = '\0'; of_getprop(p, "device_type", type, sizeof (type)); if (strncmp(type, memory, sizeof (memory)) == 0) { uint reg[48]; u64 start; u64 size; int r; int l; rc = of_getprop(p, "reg", reg, sizeof (reg)); if (rc == OF_FAILURE) { of_panic("no reg property for memory node: 0x%x.\n", p); } l = rc / sizeof(reg[0]); /* number reg element */ DBG("%s: number of bytes in property 'reg' %d\n", __func__, rc); r = 0; while (r < l) { start = reg[r++]; if (addr_cells == 2 && (r < l) ) start = (start << 32) | reg[r++]; if (r >= l) break; /* partial line. Skip */ if (start > 0) { /* this is not the first LMB so we skip it */ break; } size = reg[r++]; if (size_cells == 2 && (r < l) ) size = (size << 32) | reg[r++]; if (r > l) break; /* partial line. Skip */ boot_of_alloc_init(p, addr_cells, size_cells); eomem = size; return size; } } p = of_getpeer(p); } while (p != OF_FAILURE && p != 0); return 0;}static int save_props(void *m, ofdn_t n, int pkg){ int ret; char name[128]; int result = 1; int found_name = 0; int found_device_type = 0; const char name_str[] = "name"; const char devtype_str[] = "device_type"; /* get first */ result = of_nextprop(pkg, 0, name); while (result > 0) { int sz; u64 obj[1024]; sz = of_getproplen(pkg, name); if (sz >= 0) { ret = OF_SUCCESS; } else { ret = OF_FAILURE; } if (ret == OF_SUCCESS) { int actual = 0; ofdn_t pos; if (sz > 0) { if (sz > sizeof (obj)) { of_panic("obj array not big enough for 0x%x\n", sz); } actual = of_getprop(pkg, name, obj, sz); if (actual > sz) of_panic("obj too small"); } if (strncmp(name, name_str, sizeof(name_str)) == 0) { found_name = 1; } if (strncmp(name, devtype_str, sizeof(devtype_str)) == 0) { found_device_type = 1; } pos = ofd_prop_add(m, n, name, obj, actual); if (pos == 0) of_panic("prop_create"); } result = of_nextprop(pkg, name, name); } return 1;}static void do_pkg(void *m, ofdn_t n, int p, char *path, size_t psz){ int pnext; ofdn_t nnext; int sz;retry: save_props(m, n, p); /* do children first */ pnext = of_getchild(p); if (pnext != 0) { sz = of_package_to_path(pnext, path, psz); if (sz == OF_FAILURE) of_panic("bad path\n"); nnext = ofd_node_child_create(m, n, path, sz); if (nnext == 0) of_panic("out of mem\n"); do_pkg(m, nnext, pnext, path, psz); } /* do peer */ pnext = of_getpeer(p); if (pnext != 0) { sz = of_package_to_path(pnext, path, psz); nnext = ofd_node_peer_create(m, n, path, sz); if (nnext <= 0) of_panic("out of space in OFD tree.\n"); n = nnext; p = pnext; goto retry; }}static long pkg_save(void *mem){ int root; char path[256]; int r; path[0]='/'; path[1]='\0'; /* get root */ root = of_getpeer(0); if (root == OF_FAILURE) of_panic("no root package\n"); do_pkg(mem, OFD_ROOT, root, path, sizeof(path)); r = ofd_size(mem); of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r); return r;}static int boot_of_fixup_refs(void *mem){ static const char *fixup_props[] = { "interrupt-parent", }; int i; int count = 0; for (i = 0; i < ARRAY_SIZE(fixup_props); i++) { ofdn_t c; const char *name = fixup_props[i]; c = ofd_node_find_by_prop(mem, OFD_ROOT, name, NULL, 0); while (c > 0) { const char *path; int rp; int ref; ofdn_t dp; int rc; ofdn_t upd; char ofpath[256]; path = ofd_node_path(mem, c); if (path == NULL) of_panic("no path to found prop: %s\n", name); rp = of_finddevice(path); if (rp == OF_FAILURE) of_panic("no real device for: name %s, path %s\n", name, path); /* Note: In theory 0 is a valid node handle but it is highly * unlikely. */ if (rp == 0) { of_panic("%s: of_finddevice returns 0 for path %s\n", __func__, path); } rc = of_getprop(rp, name, &ref, sizeof(ref)); if ((rc == OF_FAILURE) || (rc == 0)) of_panic("no prop: name %s, path %s, device 0x%x\n", name, path, rp); rc = of_package_to_path(ref, ofpath, sizeof (ofpath)); if (rc == OF_FAILURE) of_panic("no package: name %s, path %s, device 0x%x,\n" "ref 0x%x\n", name, path, rp, ref); dp = ofd_node_find(mem, ofpath); if (dp <= 0) of_panic("no ofd node for OF node[0x%x]: %s\n", ref, ofpath); ref = dp; upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref)); if (upd <= 0) of_panic("update failed: %s\n", name);#ifdef DEBUG of_printf("%s: %s/%s -> %s\n", __func__, path, name, ofpath);#endif ++count; c = ofd_node_find_next(mem, c); } } return count;}static int boot_of_fixup_chosen(void *mem)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -