void planetcore_set_serial_speed(const char *table) { void *chosen, *stdout; u64 baud; u32 baud32; int len; chosen = finddevice("/chosen"); if (!chosen) return; len = getprop(chosen, "linux,stdout-path", prop_buf, MAX_PROP_LEN); if (len <= 0) return; stdout = finddevice(prop_buf); if (!stdout) { printf("planetcore_set_serial_speed: " "Bad /chosen/linux,stdout-path.\r\n"); return; } if (!planetcore_get_decimal(table, PLANETCORE_KEY_SERIAL_BAUD, &baud)) { printf("planetcore_set_serial_speed: No SB tag.\r\n"); return; } baud32 = baud; setprop(stdout, "current-speed", &baud32, 4); }
void stop_imac_ethernet(void) { void *macio, *enet; unsigned int macio_addr[5], enet_reg[6]; int len; volatile unsigned int *dbdma; macio = finddevice("/pci/mac-io"); enet = finddevice("/pci/mac-io/ethernet"); if (macio == NULL || enet == NULL) return; len = getprop(macio, "assigned-addresses", macio_addr, sizeof(macio_addr)); if (len != sizeof(macio_addr)) return; len = getprop(enet, "reg", enet_reg, sizeof(enet_reg)); if (len != sizeof(enet_reg)) return; printf("macio base %x, dma at %x & %x\n", macio_addr[2], enet_reg[2], enet_reg[4]); /* hope this is mapped... */ dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[2]); *dbdma = 0x80; /* clear the RUN bit */ eieio(); dbdma = (volatile unsigned int *) (macio_addr[2] + enet_reg[4]); *dbdma = 0x80; /* clear the RUN bit */ eieio(); }
static void ebony_flashsel_fixup(void) { void *devp; u32 reg[3] = {0x0, 0x0, 0x80000}; u8 *fpga; u8 fpga_reg0 = 0x0; devp = finddevice(EBONY_FPGA_PATH); if (!devp) fatal("Couldn't locate FPGA node %s\n\r", EBONY_FPGA_PATH); if (getprop(devp, "virtual-reg", &fpga, sizeof(fpga)) != sizeof(fpga)) fatal("%s has missing or invalid virtual-reg property\n\r", EBONY_FPGA_PATH); fpga_reg0 = in_8(fpga); devp = finddevice(EBONY_SMALL_FLASH_PATH); if (!devp) fatal("Couldn't locate small flash node %s\n\r", EBONY_SMALL_FLASH_PATH); if (getprop(devp, "reg", reg, sizeof(reg)) != sizeof(reg)) fatal("%s has reg property of unexpected size\n\r", EBONY_SMALL_FLASH_PATH); /* Invert address bit 14 (IBM-endian) if FLASH_SEL fpga bit is set */ if (fpga_reg0 & EBONY_FPGA_FLASH_SEL) reg[1] ^= 0x80000; setprop(devp, "reg", reg, sizeof(reg)); }
void planetcore_set_stdout_path(const char *table) { char *path; const char *label; void *node, *chosen; label = planetcore_get_key(table, PLANETCORE_KEY_SERIAL_PORT); if (!label) return; node = find_node_by_prop_value_str(NULL, "linux,planetcore-label", label); if (!node) return; path = get_path(node, prop_buf, MAX_PROP_LEN); if (!path) return; chosen = finddevice("/chosen"); if (!chosen) chosen = create_node(NULL, "chosen"); if (!chosen) return; setprop_str(chosen, "linux,stdout-path", path); }
static void platform_fixups(void) { u64 val; void *nvrtc; dt_fixup_memory(0, mem_size); planetcore_set_mac_addrs(table); if (!planetcore_get_decimal(table, PLANETCORE_KEY_CRYSTAL_HZ, &val)) { printf("No PlanetCore crystal frequency key.\r\n"); return; } ibm405gp_fixup_clocks(val, 0xa8c000); ibm4xx_quiesce_eth((u32 *)0xef600800, NULL); ibm4xx_fixup_ebc_ranges("/plb/ebc"); if (!planetcore_get_decimal(table, PLANETCORE_KEY_KB_NVRAM, &val)) { printf("No PlanetCore NVRAM size key.\r\n"); return; } nvrtc = finddevice("/plb/ebc/nvrtc@4,200000"); if (nvrtc != NULL) { u32 reg[3] = { 4, 0x200000, 0}; getprop(nvrtc, "reg", reg, 3); reg[2] = (val << 10) & 0xffffffff; setprop(nvrtc, "reg", reg, 3); } }
static void set_cmdline(char *buf) { void *devp; if ((devp = finddevice("/chosen"))) setprop(devp, "bootargs", buf, strlen(buf) + 1); }
void readydevice(int *maxfd,char *usbname,char *panename,int namesize) { static int count=0; finddevice(panename,usbname,"al1input","HID Keyboard Device",namesize); /*open usb keyboard device*/ if(usbname[0]) usbkbfd = open(usbname, O_RDONLY); if(usbkbfd==-1) { if(count==0) printf("Can not find usb keyboard!\n"); } else printf("Have found usb keyboard %s!\n",usbname); /*open panel device*/ if(panename[0]) panefd = open(panename, O_RDONLY); if(panefd==-1) { if(count==0) printf("Can not find panel device!\n"); } else printf("Have found panel device %s!\n",panename); /*found the max device handle for select*/ *maxfd=Max(panefd,usbkbfd); //.printf("maxfd=%d,panefd=%d,usbkbfd=%d\n",*maxfd,panefd,usbkbfd); if(count==0) count++; }
_CODE_ACCESS int remove_device(char *name) { _DEVICE *ptr; /*-------------------------------------------------------------------------*/ /* FIND RECORD AND SET NAME TO NULL */ /*-------------------------------------------------------------------------*/ /* CRITICAL REGION PROTECTS ACCESS TO _device[] */ /*-------------------------------------------------------------------------*/ __TI_resource_lock(__TI_LOCK_DEVICE_TBL); if (!(ptr = finddevice(name))) { __TI_data_synch_INV(&_device, sizeof(_device)); __TI_resource_unlock(__TI_LOCK_DEVICE_TBL); return -1; } ptr->name[0] = '\0'; __TI_data_synch_WBINV(&_device, sizeof(_device)); __TI_resource_unlock(__TI_LOCK_DEVICE_TBL); return 0; }
void dt_fixup_clock(const char *path, u32 freq) { void *devp = finddevice(path); if (devp) { printf("%s: clock-frequency <- %x (%dMHz)\n\r", path, freq, MHZ(freq)); setprop_val(devp, "clock-frequency", freq); } }
static void pq2_platform_fixups(void) { void *node; dt_fixup_memory(bd.bi_memstart, bd.bi_memsize); dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr); dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq); node = finddevice("/soc/cpm"); if (node) setprop(node, "clock-frequency", &bd.bi_cpmfreq, 4); node = finddevice("/soc/cpm/brg"); if (node) setprop(node, "clock-frequency", &bd.bi_brgfreq, 4); update_cs_ranges(); fixup_pci(); }
static int of_console_open(void) { void *devp; if (((devp = finddevice("/chosen")) != NULL) && (getprop(devp, "stdout", &of_stdout_handle, sizeof(of_stdout_handle)) == sizeof(of_stdout_handle))) return 0; return -1; }
/* For virtex, the kernel may be loaded without using a bootloader and if so some UARTs need more setup than is provided in the normal console init */ int platform_specific_init(void) { void *devp; char devtype[MAX_PROP_LEN]; char path[MAX_PATH_LEN]; devp = finddevice("/chosen"); if (devp == NULL) return -1; if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) { devp = finddevice(path); if (devp == NULL) return -1; if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0) && !strcmp(devtype, "serial") && (dt_is_compatible(devp, "ns16550"))) virtex_ns16550_console_init(devp); } return 0; }
static void *serial_get_stdout_devp(void) { void *devp; char devtype[MAX_PROP_LEN]; char path[MAX_PATH_LEN]; devp = finddevice("/chosen"); if (devp == NULL) goto err_out; if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0) { devp = finddevice(path); if (devp == NULL) goto err_out; if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0) && !strcmp(devtype, "serial")) return devp; } err_out: return NULL; }
static int check_of_version(void) { phandle oprom, chosen; char version[64]; oprom = finddevice("/openprom"); if (oprom == (phandle) -1) return 0; if (getprop(oprom, "model", version, sizeof(version)) <= 0) return 0; version[sizeof(version)-1] = 0; printf("OF version = '%s'\r\n", version); if (!string_match(version, "Open Firmware, 1.") && !string_match(version, "FirmWorks,3.")) return 0; chosen = finddevice("/chosen"); if (chosen == (phandle) -1) { chosen = finddevice("/chosen@0"); if (chosen == (phandle) -1) { printf("no chosen\n"); return 0; } } if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { printf("no mmu\n"); return 0; } memory = (ihandle) call_prom("open", 1, 1, "/memory"); if (memory == (ihandle) -1) { memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); if (memory == (ihandle) -1) { printf("no memory node\n"); return 0; } } printf("old OF detected\r\n"); return 1; }
void dt_fixup_memory(u64 start, u64 size) { void *root, *memory; int naddr, nsize, i; u32 memreg[4]; root = finddevice("/"); if (getprop(root, "#address-cells", &naddr, sizeof(naddr)) < 0) naddr = 2; if (naddr < 1 || naddr > 2) fatal("Can't cope with #address-cells == %d in /\n\r", naddr); if (getprop(root, "#size-cells", &nsize, sizeof(nsize)) < 0) nsize = 1; if (nsize < 1 || nsize > 2) fatal("Can't cope with #size-cells == %d in /\n\r", nsize); i = 0; if (naddr == 2) memreg[i++] = start >> 32; memreg[i++] = start & 0xffffffff; if (nsize == 2) memreg[i++] = size >> 32; memreg[i++] = size & 0xffffffff; memory = finddevice("/memory"); if (! memory) { memory = create_node(NULL, "memory"); setprop_str(memory, "device_type", "memory"); } printf("Memory <- <0x%x", memreg[0]); for (i = 1; i < (naddr + nsize); i++) printf(" 0x%x", memreg[i]); printf("> (%ldMB)\n\r", (unsigned long)(size >> 20)); setprop(memory, "reg", memreg, (naddr + nsize)*sizeof(u32)); }
static void get_cmdline(char *buf, int size) { void *devp; int len = strlen(builtin_cmdline); buf[0] = '\0'; if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */ len = min(len, size-1); strncpy(buf, builtin_cmdline, len); buf[len] = '\0'; } else if ((devp = finddevice("/chosen"))) getprop(devp, "bootargs", buf, size); }
static void platform_fixups(void) { void *node; dt_fixup_memory(bd.bi_memstart, bd.bi_memsize); dt_fixup_mac_addresses(bd.bi_enetaddr); dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 16, bd.bi_busfreq); node = finddevice("/soc/cpm/brg"); if (node) { printf("BRG clock-frequency <- 0x%x (%dMHz)\r\n", bd.bi_busfreq, MHZ(bd.bi_busfreq)); setprop(node, "clock-frequency", &bd.bi_busfreq, 4); } }
static void iss_4xx_fixups(void) { void *memory; u32 reg[3]; memory = finddevice("/memory"); if (!memory) fatal("Can't find memory node\n"); /* This assumes #address-cells = 2, #size-cells =1 and that */ getprop(memory, "reg", reg, sizeof(reg)); if (reg[2]) /* If the device tree specifies the memory range, use it */ ibm4xx_memstart = reg[1]; else /* othersize, read it from the SDRAM controller */ ibm4xx_sdram_fixup_memsize(); }
void start(int a1, int a2, void *promptr) { prom = (int (*)(void *)) promptr; chosen_handle = finddevice("/chosen"); if (chosen_handle == (void *) -1) exit(); if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) exit(); stderr = stdout; if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) exit(); chrpboot(a1, a2, promptr); for (;;) exit(); }
void platform_init(unsigned long null_check) { const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */ void *chosen; unsigned long ft_addr; u64 rm_size; unsigned long val; console_ops.write = ps3_console_write; platform_ops.exit = ps3_exit; printf("\n-- PS3 bootwrapper --\n"); simple_alloc_init(_end, heapsize, 32, 64); fdt_init(_dtb_start); chosen = finddevice("/chosen"); ps3_repository_read_rm_size(&rm_size); dt_fixup_memory(0, rm_size); if (_initrd_end > _initrd_start) { setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start)); setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end)); } prep_cmdline(chosen); ft_addr = dt_ops.finalize(); ps3_copy_vectors(); printf(" flat tree at 0x%lx\n\r", ft_addr); val = *(unsigned long *)0; if (val != null_check) printf("null check failed: %lx != %lx\n\r", val, null_check); ((kernel_entry_t)0)(ft_addr, 0, NULL); ps3_exit(); }
void stop_imac_usb(void) { void *usb; unsigned int usb_addr[5]; int len; volatile unsigned int *usb_ctrl; usb = finddevice("/pci/usb"); if (usb == NULL) return; len = getprop(usb, "assigned-addresses", usb_addr, sizeof(usb_addr)); if (len != sizeof(usb_addr)) return; printf("usb base %x\n", usb_addr[2]); usb_ctrl = (volatile unsigned int *) (usb_addr[2] + 8); *usb_ctrl = 0x01000000; /* cpu_to_le32(1) */ eieio(); }
static _CODE_ACCESS _DEVICE *getdevice (const char **path) { char devname[9]; char *colon = strchr(*path, ':'); _DEVICE *dev; if (colon != NULL) { int devnamlen = colon - *path; if (devnamlen > 8) devnamlen = 8; strncpy(devname, *path, devnamlen); devname[devnamlen] = '\0'; dev = finddevice(devname); if (dev) { *path = colon + 1; return dev; } } return stdevice; /* the "standard" device - host I/O */ }
int ofstdio(ihandle *stdin, ihandle *stdout, ihandle *stderr) { ihandle in, out; phandle chosen; if ((chosen = finddevice("/chosen")) == OF_INVALID_HANDLE) goto err; if (getprop(chosen, "stdout", &out, sizeof(out)) != 4) goto err; if (getprop(chosen, "stdin", &in, sizeof(in)) != 4) goto err; *stdin = in; *stdout = out; *stderr = out; return 0; err: return -1; }
static void fixup_pci(void) { struct pci_range *mem = NULL, *mmio = NULL, *io = NULL, *mem_base = NULL; u32 *pci_regs[3]; u8 *soc_regs; int i, len; void *node, *parent_node; u32 naddr, nsize, mem_pow2, mem_mask; node = finddevice("/pci"); if (!node || !dt_is_compatible(node, "fsl,pq2-pci")) return; for (i = 0; i < 3; i++) if (!dt_xlate_reg(node, i, (unsigned long *)&pci_regs[i], NULL)) goto err; soc_regs = (u8 *)fsl_get_immr(); if (!soc_regs) goto unhandled; dt_get_reg_format(node, &naddr, &nsize); if (naddr != 3 || nsize != 2) goto err; parent_node = get_parent(node); if (!parent_node) goto err; dt_get_reg_format(parent_node, &naddr, &nsize); if (naddr != 1 || nsize != 1) goto unhandled; len = getprop(node, "ranges", pci_ranges_buf, sizeof(pci_ranges_buf)); for (i = 0; i < len / sizeof(struct pci_range); i++) { u32 flags = pci_ranges_buf[i].flags & 0x43000000; if (flags == 0x42000000) mem = &pci_ranges_buf[i]; else if (flags == 0x02000000) mmio = &pci_ranges_buf[i]; else if (flags == 0x01000000) io = &pci_ranges_buf[i]; } if (!mem || !mmio || !io) goto unhandled; if (mem->size[1] != mmio->size[1]) goto unhandled; if (mem->size[1] & (mem->size[1] - 1)) goto unhandled; if (io->size[1] & (io->size[1] - 1)) goto unhandled; if (mem->phys_addr + mem->size[1] == mmio->phys_addr) mem_base = mem; else if (mmio->phys_addr + mmio->size[1] == mem->phys_addr) mem_base = mmio; else goto unhandled; out_be32(&pci_regs[1][0], mem_base->phys_addr | 1); out_be32(&pci_regs[2][0], ~(mem->size[1] + mmio->size[1] - 1)); out_be32(&pci_regs[1][1], io->phys_addr | 1); out_be32(&pci_regs[2][1], ~(io->size[1] - 1)); out_le32(&pci_regs[0][0], mem->pci_addr[1] >> 12); out_le32(&pci_regs[0][2], mem->phys_addr >> 12); out_le32(&pci_regs[0][4], (~(mem->size[1] - 1) >> 12) | 0xa0000000); out_le32(&pci_regs[0][6], mmio->pci_addr[1] >> 12); out_le32(&pci_regs[0][8], mmio->phys_addr >> 12); out_le32(&pci_regs[0][10], (~(mmio->size[1] - 1) >> 12) | 0x80000000); out_le32(&pci_regs[0][12], io->pci_addr[1] >> 12); out_le32(&pci_regs[0][14], io->phys_addr >> 12); out_le32(&pci_regs[0][16], (~(io->size[1] - 1) >> 12) | 0xc0000000); /* */ out_le32(&pci_regs[0][58], 0); out_le32(&pci_regs[0][60], 0); mem_pow2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1); mem_mask = ~(mem_pow2 - 1) >> 12; out_le32(&pci_regs[0][62], 0xa0000000 | mem_mask); /* */ if (!(in_le32(&pci_regs[0][32]) & 1)) { /* */ udelay(100000); out_le32(&pci_regs[0][32], 1); /* */ udelay(1020000); } /* */ out_le32(&pci_regs[0][64], 0x80000004); out_le32(&pci_regs[0][65], in_le32(&pci_regs[0][65]) | 6); /* */ out_8(&soc_regs[0x10028], 3); out_be32((u32 *)&soc_regs[0x1002c], 0x01236745); return; err: printf("Bad PCI node -- using existing firmware setup.\r\n"); return; unhandled: printf("Unsupported PCI node -- using existing firmware setup.\r\n"); }
void start(unsigned long a1, unsigned long a2, void *promptr) { unsigned long i; kernel_entry_t kernel_entry; Elf64_Ehdr *elf64; Elf64_Phdr *elf64ph; prom = (int (*)(void *)) promptr; chosen_handle = finddevice("/chosen"); if (chosen_handle == (void *) -1) exit(); if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) exit(); stderr = stdout; if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) exit(); printf("\n\rzImage starting: loaded at 0x%x\n\r", (unsigned)_start); /* * Now we try to claim some memory for the kernel itself * our "vmlinux_memsize" is the memory footprint in RAM, _HOWEVER_, what * our Makefile stuffs in is an image containing all sort of junk including * an ELF header. We need to do some calculations here to find the right * size... In practice we add 1Mb, that is enough, but we should really * consider fixing the Makefile to put a _raw_ kernel in there ! */ vmlinux_memsize += 0x100000; printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize); vmlinux.addr = try_claim(vmlinux_memsize); if (vmlinux.addr == 0) { printf("Can't allocate memory for kernel image !\n\r"); exit(); } vmlinuz.addr = (unsigned long)_vmlinux_start; vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); vmlinux.size = PAGE_ALIGN(vmlinux_filesize); vmlinux.memsize = vmlinux_memsize; /* * Now we try to claim memory for the initrd (and copy it there) */ initrd.size = (unsigned long)(_initrd_end - _initrd_start); initrd.memsize = initrd.size; if ( initrd.size > 0 ) { printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size); initrd.addr = try_claim(initrd.size); if (initrd.addr == 0) { printf("Can't allocate memory for initial ramdisk !\n\r"); exit(); } a1 = initrd.addr; a2 = initrd.size; printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r", initrd.addr, (unsigned long)_initrd_start, initrd.size); memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size); printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr)); } /* Eventually gunzip the kernel */ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { int len; avail_ram = scratch; begin_avail = avail_high = avail_ram; end_avail = scratch + sizeof(scratch); printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); len = vmlinuz.size; gunzip((void *)vmlinux.addr, vmlinux.size, (unsigned char *)vmlinuz.addr, &len); printf("done 0x%lx bytes\n\r", len); printf("0x%x bytes of heap consumed, max in use 0x%x\n\r", (unsigned)(avail_high - begin_avail), heap_max); } else { memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); } /* Skip over the ELF header */ elf64 = (Elf64_Ehdr *)vmlinux.addr; if ( elf64->e_ident[EI_MAG0] != ELFMAG0 || elf64->e_ident[EI_MAG1] != ELFMAG1 || elf64->e_ident[EI_MAG2] != ELFMAG2 || elf64->e_ident[EI_MAG3] != ELFMAG3 || elf64->e_ident[EI_CLASS] != ELFCLASS64 || elf64->e_ident[EI_DATA] != ELFDATA2MSB || elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64 ) { printf("Error: not a valid PPC64 ELF file!\n\r"); exit(); } elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + (unsigned long)elf64->e_phoff); for(i=0; i < (unsigned int)elf64->e_phnum ; i++,elf64ph++) { if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0) break; } #ifdef DEBUG printf("... skipping 0x%lx bytes of ELF header\n\r", (unsigned long)elf64ph->p_offset); #endif vmlinux.addr += (unsigned long)elf64ph->p_offset; vmlinux.size -= (unsigned long)elf64ph->p_offset; flush_cache((void *)vmlinux.addr, vmlinux.size); kernel_entry = (kernel_entry_t)vmlinux.addr; #ifdef DEBUG printf( "kernel:\n\r" " entry addr = 0x%lx\n\r" " a1 = 0x%lx,\n\r" " a2 = 0x%lx,\n\r" " prom = 0x%lx,\n\r" " bi_recs = 0x%lx,\n\r", (unsigned long)kernel_entry, a1, a2, (unsigned long)prom, NULL); #endif kernel_entry( a1, a2, prom, NULL ); printf("Error: Linux kernel returned to zImage bootloader!\n\r"); exit(); }
coffboot(int a1, int a2, void *prom) { void *options; unsigned loadbase; struct external_filehdr *eh; struct external_scnhdr *sp; struct external_scnhdr *isect, *rsect; int ns, oh, i; unsigned sa, len; void *dst; unsigned char *im; unsigned initrd_start, initrd_size; printf("coffboot starting\n"); options = finddevice("/options"); if (options == (void *) -1) exit(); if (getprop(options, "load-base", &loadbase, sizeof(loadbase)) != sizeof(loadbase)) { printf("error getting load-base\n"); exit(); } setup_bats(RAM_START); loadbase += RAM_START; eh = (struct external_filehdr *) loadbase; ns = get_16be(eh->f_nscns); oh = get_16be(eh->f_opthdr); sp = (struct external_scnhdr *) (loadbase + sizeof(struct external_filehdr) + oh); isect = rsect = NULL; for (i = 0; i < ns; ++i, ++sp) { if (strcmp(sp->s_name, "image") == 0) isect = sp; else if (strcmp(sp->s_name, "initrd") == 0) rsect = sp; } if (isect == NULL) { printf("image section not found\n"); exit(); } if (rsect != NULL && (initrd_size = get_32be(rsect->s_size)) != 0) { initrd_start = (RAM_END - initrd_size) & ~0xFFF; a1 = initrd_start; a2 = initrd_size; printf("initial ramdisk at %x (%u bytes)\n", initrd_start, initrd_size); memcpy((char *) initrd_start, (char *) (loadbase + get_32be(rsect->s_scnptr)), initrd_size); end_avail = (char *) initrd_start; } else { end_avail = (char *) RAM_END; } im = (unsigned char *)(loadbase + get_32be(isect->s_scnptr)); len = get_32be(isect->s_size); dst = (void *) PROG_START; if (im[0] == 0x1f && im[1] == 0x8b) { void *cp = (void *) RAM_FREE; avail_ram = (void *) (RAM_FREE + ((len + 7) & -8)); memcpy(cp, im, len); printf("gunzipping... "); gunzip(dst, 0x400000, cp, &len); printf("done\n"); } else { memmove(dst, im, len); } flush_cache(dst, len); sa = (unsigned long)dst; printf("start address = 0x%x\n", sa); #if 0 pause(); #endif { struct bi_record *rec; rec = (struct bi_record *)_ALIGN((unsigned long)dst+len+(1<<20)-1,(1<<20)); rec->tag = BI_FIRST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_BOOTLOADER_ID; sprintf( (char *)rec->data, "coffboot"); rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1; rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_MACHTYPE; rec->data[0] = _MACH_Pmac; rec->data[1] = 1; rec->size = sizeof(struct bi_record) + sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); } (*(void (*)())sa)(a1, a2, prom); printf("returned?\n"); pause(); }
void start(unsigned long a1, unsigned long a2, void *promptr, void *sp) { int len; kernel_entry_t kernel_entry; memset(__bss_start, 0, _end - __bss_start); prom = (int (*)(void *)) promptr; chosen_handle = finddevice("/chosen"); if (chosen_handle == (void *) -1) exit(); if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) exit(); printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp); /* * The first available claim_base must be above the end of the * the loaded kernel wrapper file (_start to _end includes the * initrd image if it is present) and rounded up to a nice * 1 MB boundary for good measure. */ claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB); vmlinuz.addr = (unsigned long)_vmlinux_start; vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); /* gunzip the ELF header of the kernel */ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { len = vmlinuz.size; gunzip(elfheader, sizeof(elfheader), (unsigned char *)vmlinuz.addr, &len); } else memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader)); if (!is_elf64(elfheader) && !is_elf32(elfheader)) { printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r"); exit(); } /* We need to claim the memsize plus the file offset since gzip * will expand the header (file offset), then the kernel, then * possible rubbish we don't care about. But the kernel bss must * be claimed (it will be zero'd by the kernel itself) */ printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize); vmlinux.addr = try_claim(vmlinux.memsize); if (vmlinux.addr == 0) { printf("Can't allocate memory for kernel image !\n\r"); exit(); } /* * Now we try to claim memory for the initrd (and copy it there) */ initrd.size = (unsigned long)(_initrd_end - _initrd_start); initrd.memsize = initrd.size; if ( initrd.size > 0 ) { printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size); initrd.addr = try_claim(initrd.size); if (initrd.addr == 0) { printf("Can't allocate memory for initial ramdisk !\n\r"); exit(); } a1 = initrd.addr; a2 = initrd.size; printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r", initrd.addr, (unsigned long)_initrd_start, initrd.size); memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size); printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr)); } /* Eventually gunzip the kernel */ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); len = vmlinuz.size; gunzip((void *)vmlinux.addr, vmlinux.memsize, (unsigned char *)vmlinuz.addr, &len); printf("done 0x%lx bytes\n\r", len); } else { memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); } export_cmdline(chosen_handle); /* Skip over the ELF header */ #ifdef DEBUG printf("... skipping 0x%lx bytes of ELF header\n\r", elfoffset); #endif vmlinux.addr += elfoffset; flush_cache((void *)vmlinux.addr, vmlinux.size); kernel_entry = (kernel_entry_t)vmlinux.addr; #ifdef DEBUG printf( "kernel:\n\r" " entry addr = 0x%lx\n\r" " a1 = 0x%lx,\n\r" " a2 = 0x%lx,\n\r" " prom = 0x%lx,\n\r" " bi_recs = 0x%lx,\n\r", (unsigned long)kernel_entry, a1, a2, (unsigned long)prom, NULL); #endif kernel_entry(a1, a2, prom, NULL); printf("Error: Linux kernel returned to zImage bootloader!\n\r"); exit(); }
void start(unsigned long a1, unsigned long a2, void *promptr) { unsigned long i, claim_addr, claim_size; extern char _start; struct bi_record *bi_recs; kernel_entry_t kernel_entry; Elf64_Ehdr *elf64; Elf64_Phdr *elf64ph; prom = (int (*)(void *)) promptr; chosen_handle = finddevice("/chosen"); if (chosen_handle == (void *) -1) exit(); if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4) exit(); stderr = stdout; if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4) exit(); printf("zImage starting: loaded at 0x%x\n\r", (unsigned)&_start); #if 0 sysmap.size = (unsigned long)(_sysmap_end - _sysmap_start); sysmap.memsize = sysmap.size; if ( sysmap.size > 0 ) { sysmap.addr = (RAM_END - sysmap.size) & ~0xFFF; claim(sysmap.addr, RAM_END - sysmap.addr, 0); printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r", sysmap.addr, (unsigned long)_sysmap_start, sysmap.size); memcpy((void *)sysmap.addr, (void *)_sysmap_start, sysmap.size); } #endif initrd.size = (unsigned long)(_initrd_end - _initrd_start); initrd.memsize = initrd.size; if ( initrd.size > 0 ) { initrd.addr = (RAM_END - initrd.size) & ~0xFFF; a1 = a2 = 0; claim(initrd.addr, RAM_END - initrd.addr, 0); printf("initial ramdisk moving 0x%lx <- 0x%lx (%lx bytes)\n\r", initrd.addr, (unsigned long)_initrd_start, initrd.size); memcpy((void *)initrd.addr, (void *)_initrd_start, initrd.size); } vmlinuz.addr = (unsigned long)_vmlinux_start; vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start); vmlinux.addr = (unsigned long)(void *)-1; vmlinux.size = PAGE_ALIGN(vmlinux_filesize); vmlinux.memsize = vmlinux_memsize; claim_size = vmlinux.memsize /* PPPBBB: + fudge for bi_recs */; for(claim_addr = PROG_START; claim_addr <= PROG_START * 8; claim_addr += 0x100000) { printf(" trying: 0x%08lx\n\r", claim_addr); vmlinux.addr = (unsigned long)claim(claim_addr, claim_size, 0); if ((void *)vmlinux.addr != (void *)-1) break; } if ((void *)vmlinux.addr == (void *)-1) { printf("claim error, can't allocate kernel memory\n\r"); exit(); } /* PPPBBB: should kernel always be gziped? */ if (*(unsigned short *)vmlinuz.addr == 0x1f8b) { avail_ram = scratch; begin_avail = avail_high = avail_ram; end_avail = scratch + sizeof(scratch); printf("gunzipping (0x%lx <- 0x%lx:0x%0lx)...", vmlinux.addr, vmlinuz.addr, vmlinuz.addr+vmlinuz.size); gunzip((void *)vmlinux.addr, vmlinux.size, (unsigned char *)vmlinuz.addr, (int *)&vmlinuz.size); printf("done %lu bytes\n\r", vmlinuz.size); printf("%u bytes of heap consumed, max in use %u\n\r", (unsigned)(avail_high - begin_avail), heap_max); } else { memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size); } /* Skip over the ELF header */ elf64 = (Elf64_Ehdr *)vmlinux.addr; if ( elf64->e_ident[EI_MAG0] != ELFMAG0 || elf64->e_ident[EI_MAG1] != ELFMAG1 || elf64->e_ident[EI_MAG2] != ELFMAG2 || elf64->e_ident[EI_MAG3] != ELFMAG3 || elf64->e_ident[EI_CLASS] != ELFCLASS64 || elf64->e_ident[EI_DATA] != ELFDATA2MSB || elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64 ) { printf("Error: not a valid PPC64 ELF file!\n\r"); exit(); } elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + (unsigned long)elf64->e_phoff); for(i=0; i < (unsigned int)elf64->e_phnum ;i++,elf64ph++) { if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0) break; } printf("... skipping 0x%lx bytes of ELF header\n\r", (unsigned long)elf64ph->p_offset); vmlinux.addr += (unsigned long)elf64ph->p_offset; vmlinux.size -= (unsigned long)elf64ph->p_offset; flush_cache((void *)vmlinux.addr, vmlinux.memsize); bi_recs = make_bi_recs(vmlinux.addr + vmlinux.memsize); kernel_entry = (kernel_entry_t)vmlinux.addr; printf( "kernel:\n\r" " entry addr = 0x%lx\n\r" " a1 = 0x%lx,\n\r" " a2 = 0x%lx,\n\r" " prom = 0x%lx,\n\r" " bi_recs = 0x%lx,\n\r", (unsigned long)kernel_entry, a1, a2, (unsigned long)prom, (unsigned long)bi_recs); kernel_entry( a1, a2, prom, bi_recs ); printf("Error: Linux kernel returned to zImage bootloader!\n\r"); exit(); }
int cpm_console_init(void *devp, struct serial_console_data *scdp) { void *vreg[2]; u32 reg[2]; int is_smc = 0, is_cpm2 = 0; void *parent, *muram; void *muram_addr; unsigned long muram_offset, muram_size; if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) { is_smc = 1; } else if (dt_is_compatible(devp, "fsl,cpm2-scc-uart")) { is_cpm2 = 1; } else if (dt_is_compatible(devp, "fsl,cpm2-smc-uart")) { is_cpm2 = 1; is_smc = 1; } if (is_smc) { enable_port = smc_enable_port; disable_port = smc_disable_port; } else { enable_port = scc_enable_port; disable_port = scc_disable_port; } if (is_cpm2) do_cmd = cpm2_cmd; else do_cmd = cpm1_cmd; if (getprop(devp, "fsl,cpm-command", &cpm_cmd, 4) < 4) return -1; if (dt_get_virtual_reg(devp, vreg, 2) < 2) return -1; if (is_smc) smc = vreg[0]; else scc = vreg[0]; param = vreg[1]; parent = get_parent(devp); if (!parent) return -1; if (dt_get_virtual_reg(parent, &cpcr, 1) < 1) return -1; muram = finddevice("/soc/cpm/muram/data"); if (!muram) return -1; /* For bootwrapper-compatible device trees, we assume that the first * entry has at least 128 bytes, and that #address-cells/#data-cells * is one for both parent and child. */ if (dt_get_virtual_reg(muram, &muram_addr, 1) < 1) return -1; if (getprop(muram, "reg", reg, 8) < 8) return -1; muram_offset = reg[0]; muram_size = reg[1]; /* Store the buffer descriptors at the end of the first muram chunk. * For SMC ports on CPM2-based platforms, relocate the parameter RAM * just before the buffer descriptors. */ cbd_offset = muram_offset + muram_size - 2 * sizeof(struct cpm_bd); if (is_cpm2 && is_smc) { u16 *smc_base = (u16 *)param; u16 pram_offset; pram_offset = cbd_offset - 64; pram_offset = _ALIGN_DOWN(pram_offset, 64); disable_port(); out_be16(smc_base, pram_offset); param = muram_addr - muram_offset + pram_offset; } cbd_addr = muram_addr - muram_offset + cbd_offset; scdp->open = cpm_serial_open; scdp->putc = cpm_serial_putc; scdp->getc = cpm_serial_getc; scdp->tstc = cpm_serial_tstc; return 0; }
static void update_cs_ranges(void) { void *bus_node, *parent_node; u32 *ctrl_addr; unsigned long ctrl_size; u32 naddr, nsize; int len; int i; bus_node = finddevice("/localbus"); if (!bus_node || !dt_is_compatible(bus_node, "fsl,pq2-localbus")) return; dt_get_reg_format(bus_node, &naddr, &nsize); if (naddr != 2 || nsize != 1) goto err; parent_node = get_parent(bus_node); if (!parent_node) goto err; dt_get_reg_format(parent_node, &naddr, &nsize); if (naddr != 1 || nsize != 1) goto err; if (!dt_xlate_reg(bus_node, 0, (unsigned long *)&ctrl_addr, &ctrl_size)) goto err; len = getprop(bus_node, "ranges", cs_ranges_buf, sizeof(cs_ranges_buf)); for (i = 0; i < len / sizeof(struct cs_range); i++) { u32 base, option; int cs = cs_ranges_buf[i].csnum; if (cs >= ctrl_size / 8) goto err; if (cs_ranges_buf[i].base != 0) goto err; base = in_be32(&ctrl_addr[cs * 2]); /* */ if (base & 1) { base &= 0x7fff; option = in_be32(&ctrl_addr[cs * 2 + 1]) & 0x7fff; } else { base = 0x1801; option = 0x10; } out_be32(&ctrl_addr[cs * 2], 0); out_be32(&ctrl_addr[cs * 2 + 1], option | ~(cs_ranges_buf[i].size - 1)); out_be32(&ctrl_addr[cs * 2], base | cs_ranges_buf[i].addr); } return; err: printf("Bad /localbus node\r\n"); }