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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/arm/kernel/setup.c
  3.  *
  4.  *  Copyright (C) 1995-2001 Russell King
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License version 2 as
  8.  * published by the Free Software Foundation.
  9.  */
  10. #include <linux/config.h>
  11. #include <linux/kernel.h>
  12. #include <linux/stddef.h>
  13. #include <linux/ioport.h>
  14. #include <linux/delay.h>
  15. #include <linux/utsname.h>
  16. #include <linux/blk.h>
  17. #include <linux/console.h>
  18. #include <linux/bootmem.h>
  19. #include <linux/seq_file.h>
  20. #include <linux/init.h>
  21. #include <asm/elf.h>
  22. #include <asm/hardware.h>
  23. #include <asm/io.h>
  24. #include <asm/procinfo.h>
  25. #include <asm/setup.h>
  26. #include <asm/mach-types.h>
  27. #include <asm/mach/arch.h>
  28. #include <asm/mach/irq.h>
  29. #ifndef MEM_SIZE
  30. #define MEM_SIZE (16*1024*1024)
  31. #endif
  32. #ifndef CONFIG_CMDLINE
  33. #define CONFIG_CMDLINE ""
  34. #endif
  35. #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
  36. char fpe_type[8];
  37. static int __init fpe_setup(char *line)
  38. {
  39. memcpy(fpe_type, line, 8);
  40. return 1;
  41. }
  42. __setup("fpe=", fpe_setup);
  43. #endif
  44. extern unsigned int mem_fclk_21285;
  45. extern void paging_init(struct meminfo *, struct machine_desc *desc);
  46. extern void convert_to_tag_list(struct param_struct *params, int mem_init);
  47. extern void bootmem_init(struct meminfo *);
  48. extern void reboot_setup(char *str);
  49. extern int root_mountflags;
  50. extern int _stext, _text, _etext, _edata, _end;
  51. unsigned int processor_id;
  52. unsigned int compat;
  53. unsigned int __machine_arch_type;
  54. unsigned int system_rev;
  55. unsigned int system_serial_low;
  56. unsigned int system_serial_high;
  57. unsigned int elf_hwcap;
  58. #ifdef MULTI_CPU
  59. struct processor processor;
  60. #endif
  61. unsigned char aux_device_present;
  62. char elf_platform[ELF_PLATFORM_SIZE];
  63. char saved_command_line[COMMAND_LINE_SIZE];
  64. static struct meminfo meminfo __initdata = { 0, };
  65. static struct proc_info_item proc_info;
  66. static const char *machine_name;
  67. static char command_line[COMMAND_LINE_SIZE];
  68. static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
  69. static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
  70. #define ENDIANNESS ((char)endian_test.l)
  71. /*
  72.  * Standard memory resources
  73.  */
  74. static struct resource mem_res[] = {
  75. { "Video RAM",   0,     0,     IORESOURCE_MEM },
  76. { "Kernel code", 0,     0,     IORESOURCE_MEM },
  77. { "Kernel data", 0,     0,     IORESOURCE_MEM }
  78. };
  79. #define video_ram   mem_res[0]
  80. #define kernel_code mem_res[1]
  81. #define kernel_data mem_res[2]
  82. static struct resource io_res[] = {
  83. { "reserved",    0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY },
  84. { "reserved",    0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY },
  85. { "reserved",    0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }
  86. };
  87. #define lp0 io_res[0]
  88. #define lp1 io_res[1]
  89. #define lp2 io_res[2]
  90. static void __init setup_processor(void)
  91. {
  92. extern struct proc_info_list __proc_info_begin, __proc_info_end;
  93. struct proc_info_list *list;
  94. /*
  95.  * locate processor in the list of supported processor
  96.  * types.  The linker builds this table for us from the
  97.  * entries in arch/arm/mm/proc-*.S
  98.  */
  99. for (list = &__proc_info_begin; list < &__proc_info_end ; list++)
  100. if ((processor_id & list->cpu_mask) == list->cpu_val)
  101. break;
  102. /*
  103.  * If processor type is unrecognised, then we
  104.  * can do nothing...
  105.  */
  106. if (list >= &__proc_info_end) {
  107. printk("CPU configuration botched (ID %08x), unable "
  108.        "to continue.n", processor_id);
  109. while (1);
  110. }
  111. proc_info = *list->info;
  112. #ifdef MULTI_CPU
  113. processor = *list->proc;
  114. #endif
  115. printk("Processor: %s %s revision %dn",
  116.        proc_info.manufacturer, proc_info.cpu_name,
  117.        (int)processor_id & 15);
  118. sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
  119. sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
  120. elf_hwcap = list->elf_hwcap;
  121. cpu_proc_init();
  122. }
  123. static struct machine_desc * __init setup_architecture(unsigned int nr)
  124. {
  125. extern struct machine_desc __arch_info_begin, __arch_info_end;
  126. struct machine_desc *list;
  127. /*
  128.  * locate architecture in the list of supported architectures.
  129.  */
  130. for (list = &__arch_info_begin; list < &__arch_info_end; list++)
  131. if (list->nr == nr)
  132. break;
  133. /*
  134.  * If the architecture type is not recognised, then we
  135.  * can co nothing...
  136.  */
  137. if (list >= &__arch_info_end) {
  138. printk("Architecture configuration botched (nr %d), unable "
  139.        "to continue.n", nr);
  140. while (1);
  141. }
  142. printk("Architecture: %sn", list->name);
  143. if (compat)
  144. printk(KERN_WARNING "Using compatibility code "
  145. "scheduled for removal in v%d.%d.%dn",
  146. compat >> 24, (compat >> 12) & 0x3ff,
  147. compat & 0x3ff);
  148. return list;
  149. }
  150. /*
  151.  * Initial parsing of the command line.  We need to pick out the
  152.  * memory size.  We look for mem=size@start, where start and size
  153.  * are "size[KkMm]"
  154.  */
  155. static void __init
  156. parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from)
  157. {
  158. char c = ' ', *to = command_line;
  159. int usermem = 0, len = 0;
  160. for (;;) {
  161. if (c == ' ' && !memcmp(from, "mem=", 4)) {
  162. unsigned long size, start;
  163. if (to != command_line)
  164. to -= 1;
  165. /*
  166.  * If the user specifies memory size, we
  167.  * blow away any automatically generated
  168.  * size.
  169.  */
  170. if (usermem == 0) {
  171. usermem = 1;
  172. mi->nr_banks = 0;
  173. }
  174. start = PHYS_OFFSET;
  175. size  = memparse(from + 4, &from);
  176. if (*from == '@')
  177. start = memparse(from + 1, &from);
  178. mi->bank[mi->nr_banks].start = start;
  179. mi->bank[mi->nr_banks].size  = size;
  180. mi->bank[mi->nr_banks].node  = PHYS_TO_NID(start);
  181. mi->nr_banks += 1;
  182. }
  183. c = *from++;
  184. if (!c)
  185. break;
  186. if (COMMAND_LINE_SIZE <= ++len)
  187. break;
  188. *to++ = c;
  189. }
  190. *to = '';
  191. *cmdline_p = command_line;
  192. }
  193. void __init
  194. setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
  195. {
  196. #ifdef CONFIG_BLK_DEV_RAM
  197. extern int rd_size;
  198. rd_image_start = image_start;
  199. rd_prompt = prompt;
  200. rd_doload = doload;
  201. if (rd_sz)
  202. rd_size = rd_sz;
  203. #endif
  204. }
  205. /*
  206.  * initial ram disk
  207.  */
  208. void __init setup_initrd(unsigned int start, unsigned int size)
  209. {
  210. #ifdef CONFIG_BLK_DEV_INITRD
  211. if (start == 0)
  212. size = 0;
  213. initrd_start = start;
  214. initrd_end   = start + size;
  215. #endif
  216. }
  217. static void __init
  218. request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
  219. {
  220. struct resource *res;
  221. int i;
  222. kernel_code.start  = __virt_to_phys(init_mm.start_code);
  223. kernel_code.end    = __virt_to_phys(init_mm.end_code - 1);
  224. kernel_data.start  = __virt_to_phys(init_mm.end_code);
  225. kernel_data.end    = __virt_to_phys(init_mm.brk - 1);
  226. for (i = 0; i < mi->nr_banks; i++) {
  227. unsigned long virt_start, virt_end;
  228. if (mi->bank[i].size == 0)
  229. continue;
  230. virt_start = __phys_to_virt(mi->bank[i].start);
  231. virt_end   = virt_start + mi->bank[i].size - 1;
  232. res = alloc_bootmem_low(sizeof(*res));
  233. res->name  = "System RAM";
  234. res->start = __virt_to_phys(virt_start);
  235. res->end   = __virt_to_phys(virt_end);
  236. res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
  237. request_resource(&iomem_resource, res);
  238. if (kernel_code.start >= res->start &&
  239.     kernel_code.end <= res->end)
  240. request_resource(res, &kernel_code);
  241. if (kernel_data.start >= res->start &&
  242.     kernel_data.end <= res->end)
  243. request_resource(res, &kernel_data);
  244. }
  245. if (mdesc->video_start) {
  246. video_ram.start = mdesc->video_start;
  247. video_ram.end   = mdesc->video_end;
  248. request_resource(&iomem_resource, &video_ram);
  249. }
  250. /*
  251.  * Some machines don't have the possibility of ever
  252.  * possessing lp0, lp1 or lp2
  253.  */
  254. if (mdesc->reserve_lp0)
  255. request_resource(&ioport_resource, &lp0);
  256. if (mdesc->reserve_lp1)
  257. request_resource(&ioport_resource, &lp1);
  258. if (mdesc->reserve_lp2)
  259. request_resource(&ioport_resource, &lp2);
  260. }
  261. /*
  262.  *  Tag parsing.
  263.  *
  264.  * This is the new way of passing data to the kernel at boot time.  Rather
  265.  * than passing a fixed inflexible structure to the kernel, we pass a list
  266.  * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
  267.  * tag for the list to be recognised (to distinguish the tagged list from
  268.  * a param_struct).  The list is terminated with a zero-length tag (this tag
  269.  * is not parsed in any way).
  270.  */
  271. static int __init parse_tag_core(const struct tag *tag)
  272. {
  273. if (tag->hdr.size > 2) {
  274. if ((tag->u.core.flags & 1) == 0)
  275. root_mountflags &= ~MS_RDONLY;
  276. ROOT_DEV = to_kdev_t(tag->u.core.rootdev);
  277. }
  278. return 0;
  279. }
  280. __tagtable(ATAG_CORE, parse_tag_core);
  281. static int __init parse_tag_mem32(const struct tag *tag)
  282. {
  283. if (meminfo.nr_banks >= NR_BANKS) {
  284. printk(KERN_WARNING
  285.        "Ignoring memory bank 0x%08x size %dKBn",
  286. tag->u.mem.start, tag->u.mem.size / 1024);
  287. return -EINVAL;
  288. }
  289. meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
  290. meminfo.bank[meminfo.nr_banks].size  = tag->u.mem.size;
  291. meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(tag->u.mem.start);
  292. meminfo.nr_banks += 1;
  293. return 0;
  294. }
  295. __tagtable(ATAG_MEM, parse_tag_mem32);
  296. #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
  297. struct screen_info screen_info = {
  298.  orig_video_lines: 30,
  299.  orig_video_cols: 80,
  300.  orig_video_mode: 0,
  301.  orig_video_ega_bx: 0,
  302.  orig_video_isVGA: 1,
  303.  orig_video_points: 8
  304. };
  305. static int __init parse_tag_videotext(const struct tag *tag)
  306. {
  307. screen_info.orig_x            = tag->u.videotext.x;
  308. screen_info.orig_y            = tag->u.videotext.y;
  309. screen_info.orig_video_page   = tag->u.videotext.video_page;
  310. screen_info.orig_video_mode   = tag->u.videotext.video_mode;
  311. screen_info.orig_video_cols   = tag->u.videotext.video_cols;
  312. screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
  313. screen_info.orig_video_lines  = tag->u.videotext.video_lines;
  314. screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
  315. screen_info.orig_video_points = tag->u.videotext.video_points;
  316. return 0;
  317. }
  318. __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
  319. #endif
  320. static int __init parse_tag_ramdisk(const struct tag *tag)
  321. {
  322. setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
  323.       (tag->u.ramdisk.flags & 2) == 0,
  324.       tag->u.ramdisk.start, tag->u.ramdisk.size);
  325. return 0;
  326. }
  327. __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
  328. static int __init parse_tag_initrd(const struct tag *tag)
  329. {
  330. setup_initrd(tag->u.initrd.start, tag->u.initrd.size);
  331. return 0;
  332. }
  333. __tagtable(ATAG_INITRD, parse_tag_initrd);
  334. static int __init parse_tag_serialnr(const struct tag *tag)
  335. {
  336. system_serial_low = tag->u.serialnr.low;
  337. system_serial_high = tag->u.serialnr.high;
  338. return 0;
  339. }
  340. __tagtable(ATAG_SERIAL, parse_tag_serialnr);
  341. static int __init parse_tag_revision(const struct tag *tag)
  342. {
  343. system_rev = tag->u.revision.rev;
  344. return 0;
  345. }
  346. __tagtable(ATAG_REVISION, parse_tag_revision);
  347. static int __init parse_tag_cmdline(const struct tag *tag)
  348. {
  349. strncpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
  350. default_command_line[COMMAND_LINE_SIZE - 1] = '';
  351. return 0;
  352. }
  353. __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
  354. /*
  355.  * Scan the tag table for this tag, and call its parse function.
  356.  * The tag table is built by the linker from all the __tagtable
  357.  * declarations.
  358.  */
  359. static int __init parse_tag(const struct tag *tag)
  360. {
  361. extern struct tagtable __tagtable_begin, __tagtable_end;
  362. struct tagtable *t;
  363. for (t = &__tagtable_begin; t < &__tagtable_end; t++)
  364. if (tag->hdr.tag == t->tag) {
  365. t->parse(tag);
  366. break;
  367. }
  368. return t < &__tagtable_end;
  369. }
  370. /*
  371.  * Parse all tags in the list, checking both the global and architecture
  372.  * specific tag tables.
  373.  */
  374. static void __init parse_tags(const struct tag *t)
  375. {
  376. for (; t->hdr.size; t = tag_next(t))
  377. if (!parse_tag(t))
  378. printk(KERN_WARNING
  379. "Ignoring unrecognised tag 0x%08xn",
  380. t->hdr.tag);
  381. }
  382. void __init setup_arch(char **cmdline_p)
  383. {
  384. struct tag *tags = NULL;
  385. struct machine_desc *mdesc;
  386. char *from = default_command_line;
  387. ROOT_DEV = MKDEV(0, 255);
  388. setup_processor();
  389. mdesc = setup_architecture(machine_arch_type);
  390. machine_name = mdesc->name;
  391. if (mdesc->soft_reboot)
  392. reboot_setup("s");
  393. if (mdesc->param_offset)
  394. tags = phys_to_virt(mdesc->param_offset);
  395. /*
  396.  * Do the machine-specific fixups before we parse the
  397.  * parameters or tags.
  398.  */
  399. if (mdesc->fixup)
  400. mdesc->fixup(mdesc, (struct param_struct *)tags,
  401.      &from, &meminfo);
  402. /*
  403.  * If we have the old style parameters, convert them to
  404.  * a tag list before.
  405.  */
  406. if (tags && tags->hdr.tag != ATAG_CORE)
  407. convert_to_tag_list((struct param_struct *)tags,
  408.     meminfo.nr_banks == 0);
  409. if (tags && tags->hdr.tag == ATAG_CORE)
  410. parse_tags(tags);
  411. if (meminfo.nr_banks == 0) {
  412. meminfo.nr_banks      = 1;
  413. meminfo.bank[0].start = PHYS_OFFSET;
  414. meminfo.bank[0].size  = MEM_SIZE;
  415. }
  416. init_mm.start_code = (unsigned long) &_text;
  417. init_mm.end_code   = (unsigned long) &_etext;
  418. init_mm.end_data   = (unsigned long) &_edata;
  419. init_mm.brk    = (unsigned long) &_end;
  420. memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
  421. saved_command_line[COMMAND_LINE_SIZE-1] = '';
  422. parse_cmdline(&meminfo, cmdline_p, from);
  423. bootmem_init(&meminfo);
  424. paging_init(&meminfo, mdesc);
  425. request_standard_resources(&meminfo, mdesc);
  426. /*
  427.  * Set up various architecture-specific pointers
  428.  */
  429. init_arch_irq = mdesc->init_irq;
  430. #ifdef CONFIG_VT
  431. #if defined(CONFIG_VGA_CONSOLE)
  432. conswitchp = &vga_con;
  433. #elif defined(CONFIG_DUMMY_CONSOLE)
  434. conswitchp = &dummy_con;
  435. #endif
  436. #endif
  437. }
  438. static const char *hwcap_str[] = {
  439. "swp",
  440. "half",
  441. "thumb",
  442. "26bit",
  443. "fastmult",
  444. "fpa",
  445. "vfp",
  446. "edsp",
  447. NULL
  448. };
  449. static int c_show(struct seq_file *m, void *v)
  450. {
  451. int i;
  452. seq_printf(m, "Processort: %s %s rev %d (%s)n",
  453.    proc_info.manufacturer, proc_info.cpu_name,
  454.    (int)processor_id & 15, elf_platform);
  455. seq_printf(m, "BogoMIPSt: %lu.%02lun",
  456.    loops_per_jiffy / (500000/HZ),
  457.    (loops_per_jiffy / (5000/HZ)) % 100);
  458. /* dump out the processor features */
  459. seq_puts(m, "Featurest: ");
  460. for (i = 0; hwcap_str[i]; i++)
  461. if (elf_hwcap & (1 << i))
  462. seq_printf(m, "%s ", hwcap_str[i]);
  463. seq_puts(m, "nn");
  464. seq_printf(m, "Hardwaret: %sn", machine_name);
  465. seq_printf(m, "Revisiont: %04xn", system_rev);
  466. seq_printf(m, "Serialtt: %08x%08xn",
  467.    system_serial_high, system_serial_low);
  468. return 0;
  469. }
  470. static void *c_start(struct seq_file *m, loff_t *pos)
  471. {
  472. return *pos < 1 ? (void *)1 : NULL;
  473. }
  474. static void *c_next(struct seq_file *m, void *v, loff_t *pos)
  475. {
  476. ++*pos;
  477. return NULL;
  478. }
  479. static void c_stop(struct seq_file *m, void *v)
  480. {
  481. }
  482. struct seq_operations cpuinfo_op = {
  483. start: c_start,
  484. next: c_next,
  485. stop: c_stop,
  486. show: c_show
  487. };