Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

multiboot_loader.c 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* Multiboot support
  2. *
  3. * 2003-07-02 mmap fix and header probe by SONE Takeshi
  4. */
  5. struct multiboot_mods {
  6. unsigned mod_start;
  7. unsigned mod_end;
  8. unsigned char *string;
  9. unsigned reserved;
  10. };
  11. struct multiboot_mmap {
  12. unsigned int size;
  13. unsigned int base_addr_low;
  14. unsigned int base_addr_high;
  15. unsigned int length_low;
  16. unsigned int length_high;
  17. unsigned int type;
  18. };
  19. /* The structure of a Multiboot 0.6 parameter block. */
  20. struct multiboot_info {
  21. unsigned int flags;
  22. #define MULTIBOOT_MEM_VALID 0x01
  23. #define MULTIBOOT_BOOT_DEV_VALID 0x02
  24. #define MULTIBOOT_CMDLINE_VALID 0x04
  25. #define MULTIBOOT_MODS_VALID 0x08
  26. #define MULTIBOOT_AOUT_SYMS_VALID 0x10
  27. #define MULTIBOOT_ELF_SYMS_VALID 0x20
  28. #define MULTIBOOT_MMAP_VALID 0x40
  29. unsigned int memlower;
  30. unsigned int memupper;
  31. unsigned int bootdev;
  32. unsigned int cmdline; /* physical address of the command line */
  33. unsigned mods_count;
  34. struct multiboot_mods *mods_addr;
  35. unsigned syms_num;
  36. unsigned syms_size;
  37. unsigned syms_addr;
  38. unsigned syms_shndx;
  39. unsigned mmap_length;
  40. unsigned mmap_addr;
  41. /* The structure actually ends here, so I might as well put
  42. * the ugly e820 parameters here...
  43. */
  44. struct multiboot_mmap mmap[E820MAX];
  45. };
  46. /* Multiboot image header (minimal part) */
  47. struct multiboot_header {
  48. unsigned int magic;
  49. #define MULTIBOOT_HEADER_MAGIC 0x1BADB002
  50. unsigned int flags;
  51. unsigned int checksum;
  52. };
  53. static struct multiboot_header *mbheader;
  54. static struct multiboot_info mbinfo;
  55. static void multiboot_probe(unsigned char *data, int len)
  56. {
  57. int offset;
  58. struct multiboot_header *h;
  59. /* Multiboot spec requires the header to be in first 8KB of the image */
  60. if (len > 8192)
  61. len = 8192;
  62. for (offset = 0; offset < len; offset += 4) {
  63. h = (struct multiboot_header *) (data + offset);
  64. if (h->magic == MULTIBOOT_HEADER_MAGIC
  65. && h->magic + h->flags + h->checksum == 0) {
  66. printf("/Multiboot");
  67. mbheader = h;
  68. return;
  69. }
  70. }
  71. mbheader = 0;
  72. }
  73. static inline void multiboot_boot(unsigned long entry)
  74. {
  75. unsigned char cmdline[512], *c;
  76. int i;
  77. if (!mbheader)
  78. return;
  79. /* Etherboot limits the command line to the kernel name,
  80. * default parameters and user prompted parameters. All of
  81. * them are shorter than 256 bytes. As the kernel name and
  82. * the default parameters come from the same BOOTP/DHCP entry
  83. * (or if they don't, the parameters are empty), only two
  84. * strings of the maximum size are possible. Note this buffer
  85. * can overrun if a stupid file name is chosen. Oh well. */
  86. c = cmdline;
  87. for (i = 0; KERNEL_BUF[i] != 0; i++) {
  88. switch (KERNEL_BUF[i]) {
  89. case ' ':
  90. case '\\':
  91. case '"':
  92. *c++ = '\\';
  93. break;
  94. default:
  95. break;
  96. }
  97. *c++ = KERNEL_BUF[i];
  98. }
  99. (void)sprintf(c, " -retaddr %#lX", virt_to_phys(xend32));
  100. mbinfo.flags = MULTIBOOT_MMAP_VALID | MULTIBOOT_MEM_VALID |MULTIBOOT_CMDLINE_VALID;
  101. mbinfo.memlower = meminfo.basememsize;
  102. mbinfo.memupper = meminfo.memsize;
  103. mbinfo.bootdev = 0; /* not booted from disk */
  104. mbinfo.cmdline = virt_to_phys(cmdline);
  105. for (i = 0; i < (int) meminfo.map_count; i++) {
  106. mbinfo.mmap[i].size = sizeof(struct multiboot_mmap)
  107. - sizeof(unsigned int);
  108. mbinfo.mmap[i].base_addr_low =
  109. (unsigned int) meminfo.map[i].addr;
  110. mbinfo.mmap[i].base_addr_high =
  111. (unsigned int) (meminfo.map[i].addr >> 32);
  112. mbinfo.mmap[i].length_low =
  113. (unsigned int) meminfo.map[i].size;
  114. mbinfo.mmap[i].length_high =
  115. (unsigned int) (meminfo.map[i].size >> 32);
  116. mbinfo.mmap[i].type = meminfo.map[i].type;
  117. }
  118. mbinfo.mmap_length = meminfo.map_count * sizeof(struct multiboot_mmap);
  119. mbinfo.mmap_addr = virt_to_phys(mbinfo.mmap);
  120. /* The Multiboot 0.6 spec requires all segment registers to be
  121. * loaded with an unrestricted, writeable segment.
  122. * xstart32 does this for us.
  123. */
  124. /* Start the kernel, passing the Multiboot information record
  125. * and the magic number. */
  126. os_regs.eax = 0x2BADB002;
  127. os_regs.ebx = virt_to_phys(&mbinfo);
  128. xstart32(entry);
  129. longjmp(restart_etherboot, -2);
  130. }