misc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: SCCS/s.misc.c 1.25 01/26/02 12:27:41 trini
  3.  *
  4.  * arch/ppc/boot/prep/misc.c
  5.  *
  6.  * Adapted for PowerPC by Gary Thomas
  7.  *
  8.  * Rewritten by Cort Dougan (cort@cs.nmt.edu)
  9.  * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
  10.  */
  11. #include <linux/types.h>
  12. #include <asm/residual.h>
  13. #include <linux/config.h>
  14. #include <linux/threads.h>
  15. #include <linux/elf.h>
  16. #include <linux/pci_ids.h>
  17. #include <asm/page.h>
  18. #include <asm/processor.h>
  19. #include <asm/bootinfo.h>
  20. #include <asm/mmu.h>
  21. #include <asm/byteorder.h>
  22. #include "nonstdio.h"
  23. #include "zlib.h"
  24. /*
  25.  * Please send me load/board info and such data for hardware not
  26.  * listed here so I can keep track since things are getting tricky
  27.  * with the different load addrs with different firmware.  This will
  28.  * help to avoid breaking the load/boot process.
  29.  * -- Cort
  30.  */
  31. char *avail_ram;
  32. char *end_avail;
  33. /* The linker tells us where the image is. */
  34. extern char __image_begin, __image_end;
  35. extern char __ramdisk_begin, __ramdisk_end;
  36. extern char _end[];
  37. #ifdef CONFIG_CMDLINE
  38. #define CMDLINE CONFIG_CMDLINE
  39. #else
  40. #define CMDLINE ""
  41. #endif
  42. char cmd_preset[] = CMDLINE;
  43. char cmd_buf[256];
  44. char *cmd_line = cmd_buf;
  45. int keyb_present = 1; /* keyboard controller is present by default */
  46. RESIDUAL hold_resid_buf;
  47. RESIDUAL *hold_residual = &hold_resid_buf;
  48. unsigned long initrd_size = 0;
  49. unsigned long orig_MSR;
  50. char *zimage_start;
  51. int zimage_size;
  52. #if defined(CONFIG_SERIAL_CONSOLE)
  53. unsigned long com_port;
  54. #endif /* CONFIG_SERIAL_CONSOLE */
  55. #ifdef CONFIG_VGA_CONSOLE
  56. char *vidmem = (char *)0xC00B8000;
  57. int lines = 25, cols = 80;
  58. int orig_x, orig_y = 24;
  59. #endif /* CONFIG_VGA_CONSOLE */
  60. extern int CRT_tstc(void);
  61. extern void of_init(void *handler);
  62. extern int of_finddevice(const char *device_specifier, int *phandle);
  63. extern int of_getprop(int phandle, const char *name, void *buf, int buflen,
  64. int *size);
  65. extern int vga_init(unsigned char *ISA_mem);
  66. extern void gunzip(void *, int, unsigned char *, int *);
  67. extern void _put_MSR(unsigned int val);
  68. extern unsigned long serial_init(int chan, void *ignored);
  69. extern void serial_fixups(void);
  70. void
  71. writel(unsigned int val, unsigned int address)
  72. {
  73. /* Ensure I/O operations complete */
  74. __asm__ volatile("eieio");
  75. *(unsigned int *)address = cpu_to_le32(val);
  76. }
  77. unsigned int
  78. readl(unsigned int address)
  79. {
  80. /* Ensure I/O operations complete */
  81. __asm__ volatile("eieio");
  82. return le32_to_cpu(*(unsigned int *)address);
  83. }
  84. #define PCI_CFG_ADDR(dev,off) ((0x80<<24) | (dev<<8) | (off&0xfc))
  85. #define PCI_CFG_DATA(off) (0x80000cfc+(off&3))
  86. static void
  87. pci_read_config_32(unsigned char devfn,
  88. unsigned char offset,
  89. unsigned int *val)
  90. {
  91. writel(PCI_CFG_ADDR(devfn,offset), 0x80000cf8);
  92. *val = readl(PCI_CFG_DATA(offset));
  93. return;
  94. }
  95. #ifdef CONFIG_VGA_CONSOLE
  96. void
  97. scroll(void)
  98. {
  99. int i;
  100. memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
  101. for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
  102. vidmem[i] = ' ';
  103. }
  104. #endif /* CONFIG_VGA_CONSOLE */
  105. unsigned long
  106. decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
  107.   RESIDUAL *residual, void *OFW_interface)
  108. {
  109. int timer = 0;
  110. extern unsigned long start;
  111. char *cp, ch;
  112. unsigned long TotalMemory;
  113. int dev_handle;
  114. int mem_info[2];
  115. int res, size;
  116. unsigned char board_type;
  117. unsigned char base_mod;
  118. int start_multi = 0;
  119. unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base;
  120. serial_fixups();
  121. #if defined(CONFIG_SERIAL_CONSOLE)
  122. com_port = serial_init(0, NULL);
  123. #endif /* CONFIG_SERIAL_CONSOLE */
  124. #if defined(CONFIG_VGA_CONSOLE)
  125. vga_init((unsigned char *)0xC0000000);
  126. #endif /* CONFIG_VGA_CONSOLE */
  127. /*
  128.  * Tell the user where we were loaded at and where we were relocated
  129.  * to for debugging this process.
  130.  */
  131. puts("loaded at:     "); puthex(load_addr);
  132. puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("n");
  133. if ( (unsigned long)load_addr != (unsigned long)&start ) {
  134. puts("relocated to:  "); puthex((unsigned long)&start);
  135. puts(" ");
  136. puthex((unsigned long)((unsigned long)&start + (4*num_words)));
  137. puts("n");
  138. }
  139. if (residual) {
  140. /*
  141.  * Tell the user where the residual data is.
  142.  */
  143. puts("board data at: "); puthex((unsigned long)residual);
  144. puts(" ");
  145. puthex((unsigned long)((unsigned long)residual +
  146. sizeof(RESIDUAL)));
  147. puts("nrelocated to:  ");puthex((unsigned long)hold_residual);
  148. puts(" ");
  149. puthex((unsigned long)((unsigned long)hold_residual +
  150. sizeof(RESIDUAL)));
  151. puts("n");
  152. /* Is this Motorola PPCBug? */
  153. if ((1 & residual->VitalProductData.FirmwareSupports) &&
  154.     (1 == residual->VitalProductData.FirmwareSupplier)) {
  155. board_type = inb(0x800) & 0xF0;
  156. /*
  157.  * Reset the onboard 21x4x Ethernet
  158.  * Motorola Ethernet is at IDSEL 14 (devfn 0x70)
  159.  */
  160. pci_read_config_32(0x70, 0x00, &pci_viddid);
  161. pci_did = (pci_viddid & 0xffff0000) >> 16;
  162. /* Be sure we've really found a 21x4x chip */
  163. if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_DEC) &&
  164. ((pci_did == PCI_DEVICE_ID_DEC_TULIP_FAST) ||
  165. (pci_did == PCI_DEVICE_ID_DEC_TULIP) ||
  166. (pci_did == PCI_DEVICE_ID_DEC_TULIP_PLUS) ||
  167. (pci_did == PCI_DEVICE_ID_DEC_21142))) {
  168. pci_read_config_32(0x70,
  169. 0x10,
  170. &tulip_pci_base);
  171. /* Get the physical base address */
  172. tulip_base =
  173. (tulip_pci_base & ~0x03UL) + 0x80000000;
  174. /* Strobe the 21x4x reset bit in CSR0 */
  175. writel(0x1, tulip_base);
  176. }
  177. /* If this is genesis 2 board then check for no
  178.  * keyboard controller and more than one processor.
  179.  */
  180. if (board_type == 0xe0) {
  181. base_mod = inb(0x803);
  182. /* if a MVME2300/2400 or a Sitka then no keyboard */
  183. if((base_mod == 0xFA) || (base_mod == 0xF9) ||
  184.    (base_mod == 0xE1)) {
  185. keyb_present = 0; /* no keyboard */
  186. }
  187. }
  188. /* If this is a multiprocessor system then
  189.  * park the other processor so that the
  190.  * kernel knows where to find them.
  191.  */
  192. if (residual->MaxNumCpus > 1)
  193. start_multi = 1;
  194. }
  195. memcpy(hold_residual,residual,sizeof(RESIDUAL));
  196. } else {
  197. /* Tell the user we didn't find anything. */
  198. puts("No residual data found.n");
  199. /* Assume 32M in the absence of more info... */
  200. TotalMemory = 0x02000000;
  201. /*
  202.  * This is a 'best guess' check.  We want to make sure
  203.  * we don't try this on a PReP box without OF
  204.  *     -- Cort
  205.  */
  206. while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) )
  207. {
  208. /* We need to restore the slightly inaccurate
  209.  * MSR so that OpenFirmware will behave. -- Tom
  210.  */
  211. _put_MSR(orig_MSR);
  212. of_init(OFW_interface);
  213. /* get handle to memory description */
  214. res = of_finddevice("/memory@0",
  215.     &dev_handle);
  216. if (res)
  217. break;
  218. /* get the info */
  219. res = of_getprop(dev_handle,
  220.  "reg",
  221.  mem_info,
  222.  sizeof(mem_info),
  223.  &size);
  224. if (res)
  225. break;
  226. TotalMemory = mem_info[1];
  227. break;
  228. }
  229. hold_residual->TotalMemory = TotalMemory;
  230. residual = hold_residual;
  231. /* Enforce a sane MSR for booting. */
  232. _put_MSR(MSR_IP);
  233.         }
  234. /* assume the chunk below 8M is free */
  235. end_avail = (char *)0x00800000;
  236. /*
  237.  * We link ourself to 0x00800000.  When we run, we relocate
  238.  * ourselves there.  So we just need __image_begin for the
  239.  * start. -- Tom
  240.  */
  241. zimage_start = (char *)(unsigned long)(&__image_begin);
  242. zimage_size = (unsigned long)(&__image_end) -
  243. (unsigned long)(&__image_begin);
  244. initrd_size = (unsigned long)(&__ramdisk_end) -
  245. (unsigned long)(&__ramdisk_begin);
  246. /*
  247.  * The zImage and initrd will be between start and _end, so they've
  248.  * already been moved once.  We're good to go now. -- Tom
  249.  */
  250. avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
  251. puts("zimage at:     "); puthex((unsigned long)zimage_start);
  252. puts(" "); puthex((unsigned long)(zimage_size+zimage_start));
  253. puts("n");
  254. if ( initrd_size ) {
  255. puts("initrd at:     ");
  256. puthex((unsigned long)(&__ramdisk_begin));
  257. puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("n");
  258. }
  259. avail_ram = (char *)0x00400000;
  260. end_avail = (char *)0x00800000;
  261. puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
  262. puthex((unsigned long)end_avail); puts("n");
  263. if (keyb_present)
  264. CRT_tstc();  /* Forces keyboard to be initialized */
  265. puts("nLinux/PPC load: ");
  266. cp = cmd_line;
  267. memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
  268. while ( *cp )
  269. putc(*cp++);
  270. while (timer++ < 5*1000) {
  271. if (tstc()) {
  272. while ((ch = getc()) != 'n' && ch != 'r') {
  273. /* Test for backspace/delete */
  274. if (ch == 'b' || ch == '177') {
  275. if (cp != cmd_line) {
  276. cp--;
  277. puts("b b");
  278. }
  279. /* Test for ^x/^u (and wipe the line) */
  280. } else if (ch == '30' || ch == '25') {
  281. while (cp != cmd_line) {
  282. cp--;
  283. puts("b b");
  284. }
  285. } else {
  286. *cp++ = ch;
  287. putc(ch);
  288. }
  289. }
  290. break;  /* Exit 'timer' loop */
  291. }
  292. udelay(1000);  /* 1 msec */
  293. }
  294. *cp = 0;
  295. puts("nUncompressing Linux...");
  296. gunzip(0, 0x400000, zimage_start, &zimage_size);
  297. puts("done.n");
  298. if (start_multi) {
  299. puts("Parking cpu1 at 0xc0n");
  300. residual->VitalProductData.SmpIar = (unsigned long)0xc0;
  301. residual->Cpus[1].CpuState = CPU_GOOD;
  302. hold_residual->VitalProductData.Reserved5 = 0xdeadbeef;
  303. }
  304. {
  305. struct bi_record *rec;
  306. rec = (struct bi_record *)_ALIGN((unsigned long)(zimage_size) +
  307. (1 << 20) - 1, (1 << 20));
  308. rec->tag = BI_FIRST;
  309. rec->size = sizeof(struct bi_record);
  310. rec = (struct bi_record *)((unsigned long)rec + rec->size);
  311. rec->tag = BI_BOOTLOADER_ID;
  312. memcpy( (void *)rec->data, "prepboot", 9);
  313. rec->size = sizeof(struct bi_record) + 8 + 1;
  314. rec = (struct bi_record *)((unsigned long)rec + rec->size);
  315. rec->tag = BI_MACHTYPE;
  316. rec->data[0] = _MACH_prep;
  317. rec->data[1] = 0;
  318. rec->size = sizeof(struct bi_record) + 2 *
  319. sizeof(unsigned long);
  320. rec = (struct bi_record *)((unsigned long)rec + rec->size);
  321. rec->tag = BI_CMD_LINE;
  322. memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
  323. rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
  324. rec = (struct bi_record *)((unsigned long)rec + rec->size);
  325. if ( initrd_size ) {
  326. rec->tag = BI_INITRD;
  327. rec->data[0] = (unsigned long)(&__ramdisk_begin);
  328. rec->data[1] = initrd_size;
  329. rec->size = sizeof(struct bi_record) + 2 *
  330. sizeof(unsigned long);
  331. rec = (struct bi_record *)((unsigned long)rec +
  332. rec->size);
  333. }
  334. rec->tag = BI_LAST;
  335. rec->size = sizeof(struct bi_record);
  336. rec = (struct bi_record *)((unsigned long)rec + rec->size);
  337. }
  338. puts("Now booting the kerneln");
  339. return (unsigned long)hold_residual;
  340. }