bsd.c 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/loader.h>
  19. #include <grub/i386/bsd.h>
  20. #include <grub/i386/cpuid.h>
  21. #include <grub/memory.h>
  22. #include <grub/i386/memory.h>
  23. #include <grub/file.h>
  24. #include <grub/err.h>
  25. #include <grub/dl.h>
  26. #include <grub/mm.h>
  27. #include <grub/elfload.h>
  28. #include <grub/env.h>
  29. #include <grub/misc.h>
  30. #include <grub/aout.h>
  31. #include <grub/command.h>
  32. #include <grub/extcmd.h>
  33. #include <grub/i18n.h>
  34. #include <grub/ns8250.h>
  35. #include <grub/bsdlabel.h>
  36. #include <grub/crypto.h>
  37. #include <grub/verify.h>
  38. #ifdef GRUB_MACHINE_PCBIOS
  39. #include <grub/machine/int.h>
  40. #endif
  41. GRUB_MOD_LICENSE ("GPLv3+");
  42. #include <grub/video.h>
  43. #ifdef GRUB_MACHINE_PCBIOS
  44. #include <grub/machine/biosnum.h>
  45. #endif
  46. #ifdef GRUB_MACHINE_EFI
  47. #include <grub/efi/efi.h>
  48. #define NETBSD_DEFAULT_VIDEO_MODE "800x600"
  49. #else
  50. #define NETBSD_DEFAULT_VIDEO_MODE "text"
  51. #include <grub/i386/pc/vbe.h>
  52. #endif
  53. #include <grub/video.h>
  54. #include <grub/disk.h>
  55. #include <grub/device.h>
  56. #include <grub/partition.h>
  57. #include <grub/relocator.h>
  58. #include <grub/i386/relocator.h>
  59. #define ALIGN_DWORD(a) ALIGN_UP (a, 4)
  60. #define ALIGN_QWORD(a) ALIGN_UP (a, 8)
  61. #define ALIGN_VAR(a) ((is_64bit) ? (ALIGN_QWORD(a)) : (ALIGN_DWORD(a)))
  62. #define ALIGN_PAGE(a) ALIGN_UP (a, 4096)
  63. static int kernel_type = KERNEL_TYPE_NONE;
  64. static grub_dl_t my_mod;
  65. static grub_addr_t entry, entry_hi, kern_start, kern_end;
  66. static void *kern_chunk_src;
  67. static grub_uint32_t bootflags;
  68. static int is_elf_kernel, is_64bit;
  69. static grub_uint32_t openbsd_root;
  70. static struct grub_relocator *relocator = NULL;
  71. static struct grub_openbsd_ramdisk_descriptor openbsd_ramdisk;
  72. struct bsd_tag
  73. {
  74. struct bsd_tag *next;
  75. grub_size_t len;
  76. grub_uint32_t type;
  77. union {
  78. grub_uint8_t a;
  79. grub_uint16_t b;
  80. grub_uint32_t c;
  81. } data[0];
  82. };
  83. static struct bsd_tag *tags, *tags_last;
  84. struct netbsd_module
  85. {
  86. struct netbsd_module *next;
  87. struct grub_netbsd_btinfo_module mod;
  88. };
  89. static struct netbsd_module *netbsd_mods, *netbsd_mods_last;
  90. static const struct grub_arg_option freebsd_opts[] =
  91. {
  92. {"dual", 'D', 0, N_("Display output on all consoles."), 0, 0},
  93. {"serial", 'h', 0, N_("Use serial console."), 0, 0},
  94. {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0},
  95. {"cdrom", 'C', 0, N_("Use CD-ROM as root."), 0, 0},
  96. {"config", 'c', 0, N_("Invoke user configuration routing."), 0, 0},
  97. {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0},
  98. {"gdb", 'g', 0, N_("Use GDB remote debugger instead of DDB."), 0, 0},
  99. {"mute", 'm', 0, N_("Disable all boot output."), 0, 0},
  100. {"nointr", 'n', 0, "", 0, 0},
  101. {"pause", 'p', 0, N_("Wait for keypress after every line of output."), 0, 0},
  102. {"quiet", 'q', 0, "", 0, 0},
  103. {"dfltroot", 'r', 0, N_("Use compiled-in root device."), 0, 0},
  104. {"single", 's', 0, N_("Boot into single mode."), 0, 0},
  105. {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0},
  106. {0, 0, 0, 0, 0, 0}
  107. };
  108. static const grub_uint32_t freebsd_flags[] =
  109. {
  110. FREEBSD_RB_DUAL, FREEBSD_RB_SERIAL, FREEBSD_RB_ASKNAME,
  111. FREEBSD_RB_CDROM, FREEBSD_RB_CONFIG, FREEBSD_RB_KDB,
  112. FREEBSD_RB_GDB, FREEBSD_RB_MUTE, FREEBSD_RB_NOINTR,
  113. FREEBSD_RB_PAUSE, FREEBSD_RB_QUIET, FREEBSD_RB_DFLTROOT,
  114. FREEBSD_RB_SINGLE, FREEBSD_RB_VERBOSE, 0
  115. };
  116. static const struct grub_arg_option openbsd_opts[] =
  117. {
  118. {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0},
  119. {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0},
  120. {"config", 'c', 0, N_("Change configured devices."), 0, 0},
  121. {"single", 's', 0, N_("Boot into single mode."), 0, 0},
  122. {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0},
  123. {"root", 'r', 0, N_("Set root device."), "wdXY", ARG_TYPE_STRING},
  124. {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL,
  125. N_("Use serial console."),
  126. /* TRANSLATORS: "com" is static and not to be translated. It refers to
  127. serial ports e.g. com1.
  128. */
  129. N_("comUNIT[,SPEED]"), ARG_TYPE_STRING},
  130. {0, 0, 0, 0, 0, 0}
  131. };
  132. static const grub_uint32_t openbsd_flags[] =
  133. {
  134. OPENBSD_RB_ASKNAME, OPENBSD_RB_HALT, OPENBSD_RB_CONFIG,
  135. OPENBSD_RB_SINGLE, OPENBSD_RB_KDB, 0
  136. };
  137. #define OPENBSD_ROOT_ARG (ARRAY_SIZE (openbsd_flags) - 1)
  138. #define OPENBSD_SERIAL_ARG (ARRAY_SIZE (openbsd_flags))
  139. static const struct grub_arg_option netbsd_opts[] =
  140. {
  141. {"no-smp", '1', 0, N_("Disable SMP."), 0, 0},
  142. {"no-acpi", '2', 0, N_("Disable ACPI."), 0, 0},
  143. {"askname", 'a', 0, N_("Ask for file name to reboot from."), 0, 0},
  144. {"halt", 'b', 0, N_("Don't reboot, just halt."), 0, 0},
  145. {"config", 'c', 0, N_("Change configured devices."), 0, 0},
  146. {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0},
  147. {"miniroot", 'm', 0, "", 0, 0},
  148. {"quiet", 'q', 0, N_("Don't display boot diagnostic messages."), 0, 0},
  149. {"single", 's', 0, N_("Boot into single mode."), 0, 0},
  150. {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0},
  151. {"debug", 'x', 0, N_("Boot with debug messages."), 0, 0},
  152. {"silent", 'z', 0, N_("Suppress normal output (warnings remain)."), 0, 0},
  153. {"root", 'r', 0, N_("Set root device."), N_("DEVICE"), ARG_TYPE_STRING},
  154. {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL,
  155. N_("Use serial console."),
  156. /* TRANSLATORS: "com" is static and not to be translated. It refers to
  157. serial ports e.g. com1.
  158. */
  159. N_("[ADDR|comUNIT][,SPEED]"), ARG_TYPE_STRING},
  160. {0, 0, 0, 0, 0, 0}
  161. };
  162. static const grub_uint32_t netbsd_flags[] =
  163. {
  164. NETBSD_AB_NOSMP, NETBSD_AB_NOACPI, NETBSD_RB_ASKNAME,
  165. NETBSD_RB_HALT, NETBSD_RB_USERCONFIG, NETBSD_RB_KDB,
  166. NETBSD_RB_MINIROOT, NETBSD_AB_QUIET, NETBSD_RB_SINGLE,
  167. NETBSD_AB_VERBOSE, NETBSD_AB_DEBUG, NETBSD_AB_SILENT, 0
  168. };
  169. #define NETBSD_ROOT_ARG (ARRAY_SIZE (netbsd_flags) - 1)
  170. #define NETBSD_SERIAL_ARG (ARRAY_SIZE (netbsd_flags))
  171. static void
  172. grub_bsd_get_device (grub_uint32_t * biosdev,
  173. grub_uint32_t * unit,
  174. grub_uint32_t * slice, grub_uint32_t * part)
  175. {
  176. grub_device_t dev;
  177. #ifdef GRUB_MACHINE_PCBIOS
  178. *biosdev = grub_get_root_biosnumber () & 0xff;
  179. #else
  180. *biosdev = 0xff;
  181. #endif
  182. *unit = (*biosdev & 0x7f);
  183. *slice = 0xff;
  184. *part = 0xff;
  185. dev = grub_device_open (0);
  186. if (dev && dev->disk && dev->disk->partition)
  187. {
  188. if (dev->disk->partition->parent)
  189. {
  190. *part = dev->disk->partition->number;
  191. *slice = dev->disk->partition->parent->number + 1;
  192. }
  193. else
  194. *slice = dev->disk->partition->number + 1;
  195. }
  196. if (dev)
  197. grub_device_close (dev);
  198. }
  199. static grub_err_t
  200. grub_bsd_add_meta_ptr (grub_uint32_t type, void **ptr, grub_uint32_t len)
  201. {
  202. struct bsd_tag *newtag;
  203. newtag = grub_malloc (len + sizeof (struct bsd_tag));
  204. if (!newtag)
  205. return grub_errno;
  206. newtag->len = len;
  207. newtag->type = type;
  208. newtag->next = NULL;
  209. *ptr = newtag->data;
  210. if (kernel_type == KERNEL_TYPE_FREEBSD
  211. && type == (FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_SMAP))
  212. {
  213. struct bsd_tag *p;
  214. for (p = tags;
  215. p && p->type != (FREEBSD_MODINFO_METADATA
  216. | FREEBSD_MODINFOMD_KERNEND);
  217. p = p->next);
  218. if (p)
  219. {
  220. newtag->next = p->next;
  221. p->next = newtag;
  222. if (newtag->next == NULL)
  223. tags_last = newtag;
  224. return GRUB_ERR_NONE;
  225. }
  226. }
  227. if (tags_last)
  228. tags_last->next = newtag;
  229. else
  230. tags = newtag;
  231. tags_last = newtag;
  232. return GRUB_ERR_NONE;
  233. }
  234. grub_err_t
  235. grub_bsd_add_meta (grub_uint32_t type, const void *data, grub_uint32_t len)
  236. {
  237. grub_err_t err;
  238. void *ptr;
  239. err = grub_bsd_add_meta_ptr (type, &ptr, len);
  240. if (err)
  241. return err;
  242. if (len)
  243. grub_memcpy (ptr, data, len);
  244. return GRUB_ERR_NONE;
  245. }
  246. struct grub_e820_mmap
  247. {
  248. grub_uint64_t addr;
  249. grub_uint64_t size;
  250. grub_uint32_t type;
  251. } GRUB_PACKED;
  252. #define GRUB_E820_RAM 1
  253. #define GRUB_E820_RESERVED 2
  254. #define GRUB_E820_ACPI 3
  255. #define GRUB_E820_NVS 4
  256. #define GRUB_E820_BADRAM 5
  257. #define GRUB_E820_COREBOOT_TABLES 0x10
  258. /* Context for generate_e820_mmap. */
  259. struct generate_e820_mmap_ctx
  260. {
  261. int count;
  262. struct grub_e820_mmap *mmap;
  263. struct grub_e820_mmap prev, cur;
  264. };
  265. /* Helper for generate_e820_mmap. */
  266. static int
  267. generate_e820_mmap_iter (grub_uint64_t addr, grub_uint64_t size,
  268. grub_memory_type_t type, void *data)
  269. {
  270. struct generate_e820_mmap_ctx *ctx = data;
  271. ctx->cur.addr = addr;
  272. ctx->cur.size = size;
  273. if (type == GRUB_MEMORY_COREBOOT_TABLES
  274. && addr == 0)
  275. /* Nowadays the tables at 0 don't contain anything important but
  276. *BSD needs the memory at 0 for own needs.
  277. */
  278. type = GRUB_E820_RAM;
  279. ctx->cur.type = type;
  280. /* Merge regions if possible. */
  281. if (ctx->count && ctx->cur.type == ctx->prev.type
  282. && ctx->cur.addr == ctx->prev.addr + ctx->prev.size)
  283. {
  284. ctx->prev.size += ctx->cur.size;
  285. if (ctx->mmap)
  286. ctx->mmap[-1] = ctx->prev;
  287. }
  288. else
  289. {
  290. if (ctx->mmap)
  291. *ctx->mmap++ = ctx->cur;
  292. ctx->prev = ctx->cur;
  293. ctx->count++;
  294. }
  295. if (kernel_type == KERNEL_TYPE_OPENBSD && ctx->prev.addr < 0x100000
  296. && ctx->prev.addr + ctx->prev.size > 0x100000)
  297. {
  298. ctx->cur.addr = 0x100000;
  299. ctx->cur.size = ctx->prev.addr + ctx->prev.size - 0x100000;
  300. ctx->cur.type = ctx->prev.type;
  301. ctx->prev.size = 0x100000 - ctx->prev.addr;
  302. if (ctx->mmap)
  303. {
  304. ctx->mmap[-1] = ctx->prev;
  305. ctx->mmap[0] = ctx->cur;
  306. ctx->mmap++;
  307. }
  308. ctx->prev = ctx->cur;
  309. ctx->count++;
  310. }
  311. return 0;
  312. }
  313. static void
  314. generate_e820_mmap (grub_size_t *len, grub_size_t *cnt, void *buf)
  315. {
  316. struct generate_e820_mmap_ctx ctx = {
  317. .count = 0,
  318. .mmap = buf
  319. };
  320. grub_mmap_iterate (generate_e820_mmap_iter, &ctx);
  321. if (len)
  322. *len = ctx.count * sizeof (struct grub_e820_mmap);
  323. *cnt = ctx.count;
  324. return;
  325. }
  326. static grub_err_t
  327. grub_bsd_add_mmap (void)
  328. {
  329. grub_size_t len, cnt;
  330. void *buf = NULL, *buf0;
  331. generate_e820_mmap (&len, &cnt, buf);
  332. if (kernel_type == KERNEL_TYPE_NETBSD)
  333. len += sizeof (grub_uint32_t);
  334. if (kernel_type == KERNEL_TYPE_OPENBSD)
  335. len += sizeof (struct grub_e820_mmap);
  336. buf = grub_malloc (len);
  337. if (!buf)
  338. return grub_errno;
  339. buf0 = buf;
  340. if (kernel_type == KERNEL_TYPE_NETBSD)
  341. {
  342. *(grub_uint32_t *) buf = cnt;
  343. buf = ((grub_uint32_t *) buf + 1);
  344. }
  345. generate_e820_mmap (NULL, &cnt, buf);
  346. if (kernel_type == KERNEL_TYPE_OPENBSD)
  347. grub_memset ((grub_uint8_t *) buf + len - sizeof (struct grub_e820_mmap), 0,
  348. sizeof (struct grub_e820_mmap));
  349. grub_dprintf ("bsd", "%u entries in smap\n", (unsigned) cnt);
  350. if (kernel_type == KERNEL_TYPE_NETBSD)
  351. grub_bsd_add_meta (NETBSD_BTINFO_MEMMAP, buf0, len);
  352. else if (kernel_type == KERNEL_TYPE_OPENBSD)
  353. grub_bsd_add_meta (OPENBSD_BOOTARG_MMAP, buf0, len);
  354. else
  355. grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  356. FREEBSD_MODINFOMD_SMAP, buf0, len);
  357. grub_free (buf0);
  358. return grub_errno;
  359. }
  360. grub_err_t
  361. grub_freebsd_add_meta_module (const char *filename, const char *type,
  362. int argc, char **argv,
  363. grub_addr_t addr, grub_uint32_t size)
  364. {
  365. const char *name;
  366. grub_err_t err;
  367. name = grub_strrchr (filename, '/');
  368. if (name)
  369. name++;
  370. else
  371. name = filename;
  372. if (grub_strcmp (type, "/boot/zfs/zpool.cache") == 0)
  373. name = "/boot/zfs/zpool.cache";
  374. if (grub_bsd_add_meta (FREEBSD_MODINFO_NAME, name, grub_strlen (name) + 1))
  375. return grub_errno;
  376. if (is_64bit)
  377. {
  378. grub_uint64_t addr64 = addr, size64 = size;
  379. if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1)
  380. || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr64, sizeof (addr64))
  381. || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size64, sizeof (size64)))
  382. return grub_errno;
  383. }
  384. else
  385. {
  386. if (grub_bsd_add_meta (FREEBSD_MODINFO_TYPE, type, grub_strlen (type) + 1)
  387. || grub_bsd_add_meta (FREEBSD_MODINFO_ADDR, &addr, sizeof (addr))
  388. || grub_bsd_add_meta (FREEBSD_MODINFO_SIZE, &size, sizeof (size)))
  389. return grub_errno;
  390. }
  391. if (argc)
  392. {
  393. int i, n;
  394. n = 0;
  395. for (i = 0; i < argc; i++)
  396. {
  397. n += grub_strlen (argv[i]) + 1;
  398. }
  399. if (n)
  400. {
  401. void *cmdline;
  402. char *p;
  403. if (grub_bsd_add_meta_ptr (FREEBSD_MODINFO_ARGS, &cmdline, n))
  404. return grub_errno;
  405. p = cmdline;
  406. for (i = 0; i < argc; i++)
  407. {
  408. grub_strcpy (p, argv[i]);
  409. p += grub_strlen (argv[i]);
  410. *(p++) = ' ';
  411. }
  412. *p = 0;
  413. err = grub_verify_string (cmdline, GRUB_VERIFY_MODULE_CMDLINE);
  414. if (err)
  415. return err;
  416. }
  417. }
  418. return GRUB_ERR_NONE;
  419. }
  420. static void
  421. grub_freebsd_list_modules (void)
  422. {
  423. struct bsd_tag *tag;
  424. grub_printf (" %-18s %-18s%14s%14s\n", _("name"), _("type"), _("addr"),
  425. _("size"));
  426. for (tag = tags; tag; tag = tag->next)
  427. {
  428. switch (tag->type)
  429. {
  430. case FREEBSD_MODINFO_NAME:
  431. case FREEBSD_MODINFO_TYPE:
  432. grub_printf (" %-18s", (char *) tag->data);
  433. break;
  434. case FREEBSD_MODINFO_ADDR:
  435. {
  436. grub_uint32_t addr;
  437. addr = *((grub_uint32_t *) tag->data);
  438. grub_printf (" 0x%08x", addr);
  439. break;
  440. }
  441. case FREEBSD_MODINFO_SIZE:
  442. {
  443. grub_uint32_t len;
  444. len = *((grub_uint32_t *) tag->data);
  445. grub_printf (" 0x%08x\n", len);
  446. }
  447. }
  448. }
  449. }
  450. static grub_err_t
  451. grub_netbsd_add_meta_module (char *filename, grub_uint32_t type,
  452. grub_addr_t addr, grub_uint32_t size)
  453. {
  454. char *name;
  455. struct netbsd_module *mod;
  456. name = grub_strrchr (filename, '/');
  457. if (name)
  458. name++;
  459. else
  460. name = filename;
  461. mod = grub_zalloc (sizeof (*mod));
  462. if (!mod)
  463. return grub_errno;
  464. grub_strncpy (mod->mod.name, name, sizeof (mod->mod.name) - 1);
  465. mod->mod.addr = addr;
  466. mod->mod.type = type;
  467. mod->mod.size = size;
  468. if (netbsd_mods_last)
  469. netbsd_mods_last->next = mod;
  470. else
  471. netbsd_mods = mod;
  472. netbsd_mods_last = mod;
  473. return GRUB_ERR_NONE;
  474. }
  475. static void
  476. grub_netbsd_list_modules (void)
  477. {
  478. struct netbsd_module *mod;
  479. grub_printf (" %-18s%14s%14s%14s\n", _("name"), _("type"), _("addr"),
  480. _("size"));
  481. for (mod = netbsd_mods; mod; mod = mod->next)
  482. grub_printf (" %-18s 0x%08x 0x%08x 0x%08x", mod->mod.name,
  483. mod->mod.type, mod->mod.addr, mod->mod.size);
  484. }
  485. /* This function would be here but it's under different license. */
  486. #include "bsd_pagetable.c"
  487. static grub_uint32_t freebsd_bootdev, freebsd_biosdev;
  488. static grub_uint64_t freebsd_zfsguid;
  489. static void
  490. freebsd_get_zfs (void)
  491. {
  492. grub_device_t dev;
  493. grub_fs_t fs;
  494. char *uuid;
  495. grub_err_t err;
  496. dev = grub_device_open (0);
  497. if (!dev)
  498. return;
  499. fs = grub_fs_probe (dev);
  500. if (!fs)
  501. return;
  502. if (!fs->fs_uuid || grub_strcmp (fs->name, "zfs") != 0)
  503. return;
  504. err = fs->fs_uuid (dev, &uuid);
  505. if (err)
  506. return;
  507. if (!uuid)
  508. return;
  509. freebsd_zfsguid = grub_strtoull (uuid, 0, 16);
  510. grub_free (uuid);
  511. }
  512. static grub_err_t
  513. grub_freebsd_boot (void)
  514. {
  515. struct grub_freebsd_bootinfo bi;
  516. grub_uint8_t *p, *p0;
  517. grub_addr_t p_target;
  518. grub_size_t p_size = 0;
  519. grub_err_t err;
  520. grub_size_t tag_buf_len = 0;
  521. struct grub_env_var *var;
  522. grub_memset (&bi, 0, sizeof (bi));
  523. bi.version = FREEBSD_BOOTINFO_VERSION;
  524. bi.length = sizeof (bi);
  525. bi.boot_device = freebsd_biosdev;
  526. p_size = 0;
  527. FOR_SORTED_ENV (var)
  528. if ((grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1) == 0) && (var->name[sizeof("kFreeBSD.") - 1]))
  529. {
  530. p_size += grub_strlen (&var->name[sizeof("kFreeBSD.") - 1]);
  531. p_size++;
  532. p_size += grub_strlen (var->value) + 1;
  533. }
  534. if (p_size)
  535. p_size = ALIGN_PAGE (kern_end + p_size + 1) - kern_end;
  536. if (is_elf_kernel)
  537. {
  538. struct bsd_tag *tag;
  539. err = grub_bsd_add_mmap ();
  540. if (err)
  541. return err;
  542. err = grub_bsd_add_meta (FREEBSD_MODINFO_END, 0, 0);
  543. if (err)
  544. return err;
  545. tag_buf_len = 0;
  546. for (tag = tags; tag; tag = tag->next)
  547. tag_buf_len = ALIGN_VAR (tag_buf_len
  548. + sizeof (struct freebsd_tag_header)
  549. + tag->len);
  550. p_size = ALIGN_PAGE (kern_end + p_size + tag_buf_len) - kern_end;
  551. }
  552. if (is_64bit)
  553. p_size += 4096 * 3;
  554. {
  555. grub_relocator_chunk_t ch;
  556. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  557. kern_end, p_size);
  558. if (err)
  559. return err;
  560. p = get_virtual_current_address (ch);
  561. }
  562. p_target = kern_end;
  563. p0 = p;
  564. kern_end += p_size;
  565. FOR_SORTED_ENV (var)
  566. if ((grub_memcmp (var->name, "kFreeBSD.", sizeof("kFreeBSD.") - 1) == 0) && (var->name[sizeof("kFreeBSD.") - 1]))
  567. {
  568. grub_strcpy ((char *) p, &var->name[sizeof("kFreeBSD.") - 1]);
  569. p += grub_strlen ((char *) p);
  570. *(p++) = '=';
  571. grub_strcpy ((char *) p, var->value);
  572. p += grub_strlen ((char *) p) + 1;
  573. }
  574. if (p != p0)
  575. {
  576. *(p++) = 0;
  577. bi.environment = p_target;
  578. }
  579. if (is_elf_kernel)
  580. {
  581. grub_uint8_t *p_tag = p;
  582. struct bsd_tag *tag;
  583. for (tag = tags; tag; tag = tag->next)
  584. {
  585. struct freebsd_tag_header *head
  586. = (struct freebsd_tag_header *) p_tag;
  587. head->type = tag->type;
  588. head->len = tag->len;
  589. p_tag += sizeof (struct freebsd_tag_header);
  590. switch (tag->type)
  591. {
  592. case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_HOWTO:
  593. if (is_64bit)
  594. *(grub_uint64_t *) p_tag = bootflags;
  595. else
  596. *(grub_uint32_t *) p_tag = bootflags;
  597. break;
  598. case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_ENVP:
  599. if (is_64bit)
  600. *(grub_uint64_t *) p_tag = bi.environment;
  601. else
  602. *(grub_uint32_t *) p_tag = bi.environment;
  603. break;
  604. case FREEBSD_MODINFO_METADATA | FREEBSD_MODINFOMD_KERNEND:
  605. if (is_64bit)
  606. *(grub_uint64_t *) p_tag = kern_end;
  607. else
  608. *(grub_uint32_t *) p_tag = kern_end;
  609. break;
  610. default:
  611. grub_memcpy (p_tag, tag->data, tag->len);
  612. break;
  613. }
  614. p_tag += tag->len;
  615. p_tag = ALIGN_VAR (p_tag - p) + p;
  616. }
  617. bi.tags = (p - p0) + p_target;
  618. p = (ALIGN_PAGE ((p_tag - p0) + p_target) - p_target) + p0;
  619. }
  620. bi.kern_end = kern_end;
  621. grub_video_set_mode ("text", 0, 0);
  622. if (is_64bit)
  623. {
  624. struct grub_relocator64_state state;
  625. grub_uint8_t *pagetable;
  626. grub_uint32_t *stack;
  627. grub_addr_t stack_target;
  628. {
  629. grub_relocator_chunk_t ch;
  630. err = grub_relocator_alloc_chunk_align (relocator, &ch,
  631. 0x10000, 0x90000,
  632. 3 * sizeof (grub_uint32_t)
  633. + sizeof (bi), 4,
  634. GRUB_RELOCATOR_PREFERENCE_NONE,
  635. 0);
  636. if (err)
  637. return err;
  638. stack = get_virtual_current_address (ch);
  639. stack_target = get_physical_target_address (ch);
  640. }
  641. #ifdef GRUB_MACHINE_EFI
  642. err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
  643. if (err)
  644. return err;
  645. #endif
  646. pagetable = p;
  647. fill_bsd64_pagetable (pagetable, (pagetable - p0) + p_target);
  648. state.cr3 = (pagetable - p0) + p_target;
  649. state.rsp = stack_target;
  650. state.rip = (((grub_uint64_t) entry_hi) << 32) | entry;
  651. stack[0] = entry;
  652. stack[1] = bi.tags;
  653. stack[2] = kern_end;
  654. return grub_relocator64_boot (relocator, state, 0, 0x40000000);
  655. }
  656. else
  657. {
  658. struct grub_relocator32_state state;
  659. grub_uint32_t *stack;
  660. grub_addr_t stack_target;
  661. {
  662. grub_relocator_chunk_t ch;
  663. err = grub_relocator_alloc_chunk_align (relocator, &ch,
  664. 0x10000, 0x90000,
  665. 9 * sizeof (grub_uint32_t)
  666. + sizeof (bi), 4,
  667. GRUB_RELOCATOR_PREFERENCE_NONE,
  668. 0);
  669. if (err)
  670. return err;
  671. stack = get_virtual_current_address (ch);
  672. stack_target = get_physical_target_address (ch);
  673. }
  674. #ifdef GRUB_MACHINE_EFI
  675. err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
  676. if (err)
  677. return err;
  678. #endif
  679. grub_memcpy (&stack[9], &bi, sizeof (bi));
  680. state.eip = entry;
  681. state.esp = stack_target;
  682. state.ebp = stack_target;
  683. stack[0] = entry; /* "Return" address. */
  684. stack[1] = bootflags | FREEBSD_RB_BOOTINFO;
  685. stack[2] = freebsd_bootdev;
  686. stack[3] = freebsd_zfsguid ? 4 : 0;
  687. stack[4] = freebsd_zfsguid;
  688. stack[5] = freebsd_zfsguid >> 32;
  689. stack[6] = stack_target + 9 * sizeof (grub_uint32_t);
  690. stack[7] = bi.tags;
  691. stack[8] = kern_end;
  692. return grub_relocator32_boot (relocator, state, 0);
  693. }
  694. /* Not reached. */
  695. return GRUB_ERR_NONE;
  696. }
  697. static grub_err_t
  698. grub_openbsd_boot (void)
  699. {
  700. grub_uint32_t *stack;
  701. struct grub_relocator32_state state;
  702. void *curarg, *buf0, *arg0;
  703. grub_addr_t buf_target;
  704. grub_err_t err;
  705. grub_size_t tag_buf_len;
  706. err = grub_bsd_add_mmap ();
  707. if (err)
  708. return err;
  709. #ifdef GRUB_MACHINE_PCBIOS
  710. {
  711. struct grub_bios_int_registers regs;
  712. regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
  713. regs.ebx = 0;
  714. regs.ecx = 0;
  715. regs.eax = 0xb101;
  716. regs.es = 0;
  717. regs.edi = 0;
  718. regs.edx = 0;
  719. grub_bios_interrupt (0x1a, &regs);
  720. if (regs.edx == 0x20494350)
  721. {
  722. struct grub_openbsd_bootarg_pcibios pcibios;
  723. pcibios.characteristics = regs.eax & 0xff;
  724. pcibios.revision = regs.ebx & 0xffff;
  725. pcibios.pm_entry = regs.edi;
  726. pcibios.last_bus = regs.ecx & 0xff;
  727. grub_bsd_add_meta (OPENBSD_BOOTARG_PCIBIOS, &pcibios,
  728. sizeof (pcibios));
  729. }
  730. }
  731. #endif
  732. {
  733. struct bsd_tag *tag;
  734. tag_buf_len = 0;
  735. for (tag = tags; tag; tag = tag->next)
  736. tag_buf_len = ALIGN_VAR (tag_buf_len
  737. + sizeof (struct grub_openbsd_bootargs)
  738. + tag->len);
  739. }
  740. buf_target = GRUB_BSD_TEMP_BUFFER - 9 * sizeof (grub_uint32_t);
  741. {
  742. grub_relocator_chunk_t ch;
  743. err = grub_relocator_alloc_chunk_addr (relocator, &ch, buf_target,
  744. tag_buf_len
  745. + sizeof (struct grub_openbsd_bootargs)
  746. + 9 * sizeof (grub_uint32_t));
  747. if (err)
  748. return err;
  749. buf0 = get_virtual_current_address (ch);
  750. }
  751. stack = (grub_uint32_t *) buf0;
  752. arg0 = curarg = stack + 9;
  753. {
  754. struct bsd_tag *tag;
  755. struct grub_openbsd_bootargs *head;
  756. for (tag = tags; tag; tag = tag->next)
  757. {
  758. head = curarg;
  759. head->ba_type = tag->type;
  760. head->ba_size = tag->len + sizeof (*head);
  761. curarg = head + 1;
  762. grub_memcpy (curarg, tag->data, tag->len);
  763. curarg = (grub_uint8_t *) curarg + tag->len;
  764. head->ba_next = (grub_uint8_t *) curarg - (grub_uint8_t *) buf0
  765. + buf_target;
  766. }
  767. head = curarg;
  768. head->ba_type = OPENBSD_BOOTARG_END;
  769. head->ba_size = 0;
  770. head->ba_next = 0;
  771. }
  772. grub_video_set_mode ("text", 0, 0);
  773. #ifdef GRUB_MACHINE_EFI
  774. err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
  775. if (err)
  776. return err;
  777. #endif
  778. state.eip = entry;
  779. state.ebp = state.esp
  780. = ((grub_uint8_t *) stack - (grub_uint8_t *) buf0) + buf_target;
  781. stack[0] = entry;
  782. stack[1] = bootflags;
  783. stack[2] = openbsd_root;
  784. stack[3] = OPENBSD_BOOTARG_APIVER;
  785. stack[4] = 0;
  786. stack[5] = grub_mmap_get_upper () >> 10;
  787. stack[6] = grub_mmap_get_lower () >> 10;
  788. stack[7] = (grub_uint8_t *) curarg - (grub_uint8_t *) arg0;
  789. stack[8] = ((grub_uint8_t *) arg0 - (grub_uint8_t *) buf0) + buf_target;
  790. return grub_relocator32_boot (relocator, state, 0);
  791. }
  792. static grub_err_t
  793. grub_netbsd_setup_video (void)
  794. {
  795. struct grub_video_mode_info mode_info;
  796. void *framebuffer;
  797. const char *modevar;
  798. struct grub_netbsd_btinfo_framebuf params;
  799. grub_err_t err;
  800. grub_video_driver_id_t driv_id;
  801. modevar = grub_env_get ("gfxpayload");
  802. /* Now all graphical modes are acceptable.
  803. May change in future if we have modes without framebuffer. */
  804. if (modevar && *modevar != 0)
  805. {
  806. char *tmp;
  807. tmp = grub_xasprintf ("%s;" NETBSD_DEFAULT_VIDEO_MODE, modevar);
  808. if (! tmp)
  809. return grub_errno;
  810. err = grub_video_set_mode (tmp, 0, 0);
  811. grub_free (tmp);
  812. }
  813. else
  814. err = grub_video_set_mode (NETBSD_DEFAULT_VIDEO_MODE, 0, 0);
  815. if (err)
  816. return err;
  817. driv_id = grub_video_get_driver_id ();
  818. if (driv_id == GRUB_VIDEO_DRIVER_NONE)
  819. return GRUB_ERR_NONE;
  820. err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
  821. if (err)
  822. return err;
  823. params.width = mode_info.width;
  824. params.height = mode_info.height;
  825. params.bpp = mode_info.bpp;
  826. params.pitch = mode_info.pitch;
  827. params.flags = 0;
  828. params.fbaddr = (grub_addr_t) framebuffer;
  829. params.red_mask_size = mode_info.red_mask_size;
  830. params.red_field_pos = mode_info.red_field_pos;
  831. params.green_mask_size = mode_info.green_mask_size;
  832. params.green_field_pos = mode_info.green_field_pos;
  833. params.blue_mask_size = mode_info.blue_mask_size;
  834. params.blue_field_pos = mode_info.blue_field_pos;
  835. #ifdef GRUB_MACHINE_PCBIOS
  836. /* VESA packed modes may come with zeroed mask sizes, which need
  837. to be set here according to DAC Palette width. If we don't,
  838. this results in Linux displaying a black screen. */
  839. if (mode_info.bpp <= 8 && driv_id == GRUB_VIDEO_DRIVER_VBE)
  840. {
  841. struct grub_vbe_info_block controller_info;
  842. int status;
  843. int width = 8;
  844. status = grub_vbe_bios_get_controller_info (&controller_info);
  845. if (status == GRUB_VBE_STATUS_OK &&
  846. (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH))
  847. status = grub_vbe_bios_set_dac_palette_width (&width);
  848. if (status != GRUB_VBE_STATUS_OK)
  849. /* 6 is default after mode reset. */
  850. width = 6;
  851. params.red_mask_size = params.green_mask_size
  852. = params.blue_mask_size = width;
  853. }
  854. #endif
  855. err = grub_bsd_add_meta (NETBSD_BTINFO_FRAMEBUF, &params, sizeof (params));
  856. return err;
  857. }
  858. static grub_err_t
  859. grub_netbsd_add_modules (void)
  860. {
  861. struct netbsd_module *mod;
  862. unsigned modcnt = 0;
  863. struct grub_netbsd_btinfo_modules *mods;
  864. unsigned i;
  865. grub_err_t err;
  866. for (mod = netbsd_mods; mod; mod = mod->next)
  867. modcnt++;
  868. mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt);
  869. if (!mods)
  870. return grub_errno;
  871. mods->num = modcnt;
  872. mods->last_addr = kern_end;
  873. for (mod = netbsd_mods, i = 0; mod; i++, mod = mod->next)
  874. mods->mods[i] = mod->mod;
  875. err = grub_bsd_add_meta (NETBSD_BTINFO_MODULES, mods,
  876. sizeof (*mods) + sizeof (mods->mods[0]) * modcnt);
  877. grub_free (mods);
  878. return err;
  879. }
  880. /*
  881. * Adds NetBSD bootinfo bootdisk and bootwedge. The partition identified
  882. * in these bootinfo fields is the root device.
  883. */
  884. static void
  885. grub_netbsd_add_boot_disk_and_wedge (void)
  886. {
  887. grub_device_t dev;
  888. grub_disk_t disk;
  889. grub_partition_t part;
  890. grub_uint32_t biosdev;
  891. grub_uint32_t partmapsector;
  892. union {
  893. grub_uint64_t raw[GRUB_DISK_SECTOR_SIZE / 8];
  894. struct grub_partition_bsd_disk_label label;
  895. } buf;
  896. if (GRUB_MD_MD5->mdlen > GRUB_CRYPTO_MAX_MDLEN)
  897. {
  898. grub_error (GRUB_ERR_BUG, "mdlen too long");
  899. return;
  900. }
  901. dev = grub_device_open (0);
  902. if (! (dev && dev->disk && dev->disk->partition))
  903. goto fail;
  904. disk = dev->disk;
  905. part = disk->partition;
  906. if (disk->dev && disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID)
  907. biosdev = (grub_uint32_t) disk->id & 0xff;
  908. else
  909. biosdev = 0xff;
  910. /* Absolute sector of the partition map describing this partition. */
  911. partmapsector = grub_partition_get_start (part->parent) + part->offset;
  912. disk->partition = part->parent;
  913. if (grub_disk_read (disk, part->offset, 0, GRUB_DISK_SECTOR_SIZE, buf.raw)
  914. != GRUB_ERR_NONE)
  915. goto fail;
  916. disk->partition = part;
  917. /* Fill bootwedge. */
  918. {
  919. struct grub_netbsd_btinfo_bootwedge biw;
  920. grub_uint8_t hash[GRUB_CRYPTO_MAX_MDLEN];
  921. grub_memset (&biw, 0, sizeof (biw));
  922. biw.biosdev = biosdev;
  923. biw.startblk = grub_partition_get_start (part);
  924. biw.nblks = part->len;
  925. biw.matchblk = partmapsector;
  926. biw.matchnblks = 1;
  927. grub_crypto_hash (GRUB_MD_MD5, hash,
  928. buf.raw, GRUB_DISK_SECTOR_SIZE);
  929. grub_memcpy (biw.matchhash, hash, 16);
  930. grub_bsd_add_meta (NETBSD_BTINFO_BOOTWEDGE, &biw, sizeof (biw));
  931. }
  932. /* Fill bootdisk. */
  933. {
  934. struct grub_netbsd_btinfo_bootdisk bid;
  935. grub_memset (&bid, 0, sizeof (bid));
  936. /* Check for a NetBSD disk label. */
  937. if (part->partmap != NULL &&
  938. (grub_strcmp (part->partmap->name, "netbsd") == 0 ||
  939. (part->parent == NULL && grub_strcmp (part->partmap->name, "bsd") == 0)))
  940. {
  941. bid.labelsector = partmapsector;
  942. bid.label.type = buf.label.type;
  943. bid.label.checksum = buf.label.checksum;
  944. grub_memcpy (bid.label.packname, buf.label.packname, 16);
  945. }
  946. else
  947. {
  948. bid.labelsector = -1;
  949. }
  950. bid.biosdev = biosdev;
  951. bid.partition = part->number;
  952. grub_bsd_add_meta (NETBSD_BTINFO_BOOTDISK, &bid, sizeof (bid));
  953. }
  954. fail:
  955. if (dev)
  956. grub_device_close (dev);
  957. }
  958. static grub_err_t
  959. grub_netbsd_boot (void)
  960. {
  961. struct grub_netbsd_bootinfo *bootinfo;
  962. void *curarg, *arg0;
  963. grub_addr_t arg_target, stack_target;
  964. grub_uint32_t *stack;
  965. grub_err_t err;
  966. struct grub_relocator32_state state;
  967. grub_size_t tag_buf_len = 0;
  968. int tag_count = 0;
  969. err = grub_bsd_add_mmap ();
  970. if (err)
  971. return err;
  972. err = grub_netbsd_setup_video ();
  973. if (err)
  974. {
  975. grub_print_error ();
  976. grub_puts_ (N_("Booting in blind mode"));
  977. grub_errno = GRUB_ERR_NONE;
  978. }
  979. err = grub_netbsd_add_modules ();
  980. if (err)
  981. return err;
  982. #ifdef GRUB_MACHINE_EFI
  983. err = grub_bsd_add_meta (NETBSD_BTINFO_EFI,
  984. &grub_efi_system_table,
  985. sizeof (grub_efi_system_table));
  986. if (err)
  987. return err;
  988. #endif
  989. {
  990. struct bsd_tag *tag;
  991. tag_buf_len = 0;
  992. for (tag = tags; tag; tag = tag->next)
  993. {
  994. tag_buf_len = ALIGN_VAR (tag_buf_len
  995. + sizeof (struct grub_netbsd_btinfo_common)
  996. + tag->len);
  997. tag_count++;
  998. }
  999. }
  1000. arg_target = kern_end;
  1001. {
  1002. grub_relocator_chunk_t ch;
  1003. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  1004. arg_target, tag_buf_len
  1005. + sizeof (struct grub_netbsd_bootinfo)
  1006. + tag_count * sizeof (grub_uint32_t));
  1007. if (err)
  1008. return err;
  1009. curarg = get_virtual_current_address (ch);
  1010. }
  1011. arg0 = curarg;
  1012. bootinfo = (void *) ((grub_uint8_t *) arg0 + tag_buf_len);
  1013. {
  1014. struct bsd_tag *tag;
  1015. unsigned i;
  1016. bootinfo->bi_count = tag_count;
  1017. for (tag = tags, i = 0; tag; i++, tag = tag->next)
  1018. {
  1019. struct grub_netbsd_btinfo_common *head = curarg;
  1020. bootinfo->bi_data[i] = ((grub_uint8_t *) curarg - (grub_uint8_t *) arg0)
  1021. + arg_target;
  1022. head->type = tag->type;
  1023. head->len = tag->len + sizeof (*head);
  1024. curarg = head + 1;
  1025. grub_memcpy (curarg, tag->data, tag->len);
  1026. curarg = (grub_uint8_t *) curarg + tag->len;
  1027. }
  1028. }
  1029. {
  1030. grub_relocator_chunk_t ch;
  1031. err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x10000, 0x90000,
  1032. 7 * sizeof (grub_uint32_t), 4,
  1033. GRUB_RELOCATOR_PREFERENCE_NONE,
  1034. 0);
  1035. if (err)
  1036. return err;
  1037. stack = get_virtual_current_address (ch);
  1038. stack_target = get_physical_target_address (ch);
  1039. }
  1040. #ifdef GRUB_MACHINE_EFI
  1041. err = grub_efi_finish_boot_services (NULL, NULL, NULL, NULL, NULL);
  1042. if (err)
  1043. return err;
  1044. #endif
  1045. state.eip = entry;
  1046. state.esp = stack_target;
  1047. state.ebp = stack_target;
  1048. stack[0] = entry;
  1049. stack[1] = bootflags;
  1050. stack[2] = 0;
  1051. stack[3] = ((grub_uint8_t *) bootinfo - (grub_uint8_t *) arg0) + arg_target;
  1052. stack[4] = 0;
  1053. stack[5] = grub_mmap_get_upper () >> 10;
  1054. stack[6] = grub_mmap_get_lower () >> 10;
  1055. return grub_relocator32_boot (relocator, state, 0);
  1056. }
  1057. static grub_err_t
  1058. grub_bsd_unload (void)
  1059. {
  1060. struct bsd_tag *tag, *next;
  1061. for (tag = tags; tag; tag = next)
  1062. {
  1063. next = tag->next;
  1064. grub_free (tag);
  1065. }
  1066. tags = NULL;
  1067. tags_last = NULL;
  1068. kernel_type = KERNEL_TYPE_NONE;
  1069. grub_dl_unref (my_mod);
  1070. grub_relocator_unload (relocator);
  1071. relocator = NULL;
  1072. return GRUB_ERR_NONE;
  1073. }
  1074. static grub_err_t
  1075. grub_bsd_load_aout (grub_file_t file, const char *filename)
  1076. {
  1077. grub_addr_t load_addr, load_end;
  1078. int ofs, align_page;
  1079. union grub_aout_header ah;
  1080. grub_err_t err;
  1081. grub_size_t bss_size;
  1082. if ((grub_file_seek (file, 0)) == (grub_off_t) - 1)
  1083. return grub_errno;
  1084. if (grub_file_read (file, &ah, sizeof (ah)) != sizeof (ah))
  1085. {
  1086. if (!grub_errno)
  1087. grub_error (GRUB_ERR_READ_ERROR, N_("premature end of file %s"),
  1088. filename);
  1089. return grub_errno;
  1090. }
  1091. if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32)
  1092. return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header");
  1093. entry = ah.aout32.a_entry & 0xFFFFFF;
  1094. if (AOUT_GETMAGIC (ah.aout32) == AOUT32_ZMAGIC)
  1095. {
  1096. load_addr = entry;
  1097. ofs = 0x1000;
  1098. align_page = 0;
  1099. }
  1100. else
  1101. {
  1102. load_addr = entry & 0xF00000;
  1103. ofs = sizeof (struct grub_aout32_header);
  1104. align_page = 1;
  1105. }
  1106. if (load_addr < 0x100000)
  1107. return grub_error (GRUB_ERR_BAD_OS, "load address below 1M");
  1108. kern_start = load_addr;
  1109. load_end = kern_end = load_addr + ah.aout32.a_text + ah.aout32.a_data;
  1110. if (align_page)
  1111. kern_end = ALIGN_PAGE (kern_end);
  1112. if (ah.aout32.a_bss)
  1113. {
  1114. kern_end += ah.aout32.a_bss;
  1115. if (align_page)
  1116. kern_end = ALIGN_PAGE (kern_end);
  1117. bss_size = kern_end - load_end;
  1118. }
  1119. else
  1120. bss_size = 0;
  1121. {
  1122. grub_relocator_chunk_t ch;
  1123. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  1124. kern_start, kern_end - kern_start);
  1125. if (err)
  1126. return err;
  1127. kern_chunk_src = get_virtual_current_address (ch);
  1128. }
  1129. return grub_aout_load (file, ofs, kern_chunk_src,
  1130. ah.aout32.a_text + ah.aout32.a_data,
  1131. bss_size);
  1132. }
  1133. static grub_err_t
  1134. grub_bsd_load_elf (grub_elf_t elf, const char *filename)
  1135. {
  1136. grub_err_t err;
  1137. kern_end = 0;
  1138. kern_start = ~0;
  1139. if (grub_elf_is_elf32 (elf))
  1140. {
  1141. grub_relocator_chunk_t ch;
  1142. Elf32_Phdr *phdr;
  1143. entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFFF;
  1144. FOR_ELF32_PHDRS (elf, phdr)
  1145. {
  1146. Elf32_Addr paddr;
  1147. if (phdr->p_type != PT_LOAD
  1148. && phdr->p_type != PT_DYNAMIC)
  1149. continue;
  1150. paddr = phdr->p_paddr & 0xFFFFFFF;
  1151. if (paddr < kern_start)
  1152. kern_start = paddr;
  1153. if (paddr + phdr->p_memsz > kern_end)
  1154. kern_end = paddr + phdr->p_memsz;
  1155. }
  1156. if (grub_errno)
  1157. return grub_errno;
  1158. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  1159. kern_start, kern_end - kern_start);
  1160. if (err)
  1161. return err;
  1162. kern_chunk_src = get_virtual_current_address (ch);
  1163. err = grub_elf32_load (elf, filename, (grub_uint8_t *) kern_chunk_src - kern_start, GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC | GRUB_ELF_LOAD_FLAGS_28BITS, 0, 0);
  1164. if (err)
  1165. return err;
  1166. if (kernel_type != KERNEL_TYPE_OPENBSD)
  1167. return GRUB_ERR_NONE;
  1168. return grub_openbsd_find_ramdisk32 (elf->file, filename, kern_start,
  1169. kern_chunk_src, &openbsd_ramdisk);
  1170. }
  1171. else if (grub_elf_is_elf64 (elf))
  1172. {
  1173. Elf64_Phdr *phdr;
  1174. is_64bit = 1;
  1175. if (! grub_cpuid_has_longmode)
  1176. return grub_error (GRUB_ERR_BAD_OS, "your CPU does not implement AMD64 architecture");
  1177. /* FreeBSD has 64-bit entry point. */
  1178. if (kernel_type == KERNEL_TYPE_FREEBSD)
  1179. {
  1180. entry = elf->ehdr.ehdr64.e_entry & 0xffffffff;
  1181. entry_hi = (elf->ehdr.ehdr64.e_entry >> 32) & 0xffffffff;
  1182. }
  1183. else
  1184. {
  1185. entry = elf->ehdr.ehdr64.e_entry & 0x0fffffff;
  1186. entry_hi = 0;
  1187. }
  1188. FOR_ELF64_PHDRS (elf, phdr)
  1189. {
  1190. Elf64_Addr paddr;
  1191. if (phdr->p_type != PT_LOAD
  1192. && phdr->p_type != PT_DYNAMIC)
  1193. continue;
  1194. paddr = phdr->p_paddr & 0xFFFFFFF;
  1195. if (paddr < kern_start)
  1196. kern_start = paddr;
  1197. if (paddr + phdr->p_memsz > kern_end)
  1198. kern_end = paddr + phdr->p_memsz;
  1199. }
  1200. if (grub_errno)
  1201. return grub_errno;
  1202. grub_dprintf ("bsd", "kern_start = %lx, kern_end = %lx\n",
  1203. (unsigned long) kern_start, (unsigned long) kern_end);
  1204. {
  1205. grub_relocator_chunk_t ch;
  1206. err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_start,
  1207. kern_end - kern_start);
  1208. if (err)
  1209. return err;
  1210. kern_chunk_src = get_virtual_current_address (ch);
  1211. }
  1212. err = grub_elf64_load (elf, filename,
  1213. (grub_uint8_t *) kern_chunk_src - kern_start, GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC | GRUB_ELF_LOAD_FLAGS_28BITS, 0, 0);
  1214. if (err)
  1215. return err;
  1216. if (kernel_type != KERNEL_TYPE_OPENBSD)
  1217. return GRUB_ERR_NONE;
  1218. return grub_openbsd_find_ramdisk64 (elf->file, filename, kern_start,
  1219. kern_chunk_src, &openbsd_ramdisk);
  1220. }
  1221. else
  1222. return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
  1223. }
  1224. static grub_err_t
  1225. grub_bsd_load (int argc, char *argv[])
  1226. {
  1227. grub_file_t file;
  1228. grub_elf_t elf;
  1229. grub_dl_ref (my_mod);
  1230. grub_loader_unset ();
  1231. grub_memset (&openbsd_ramdisk, 0, sizeof (openbsd_ramdisk));
  1232. if (argc == 0)
  1233. {
  1234. grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  1235. goto fail;
  1236. }
  1237. file = grub_file_open (argv[0], GRUB_FILE_TYPE_BSD_KERNEL);
  1238. if (!file)
  1239. goto fail;
  1240. relocator = grub_relocator_new ();
  1241. if (!relocator)
  1242. {
  1243. grub_file_close (file);
  1244. goto fail;
  1245. }
  1246. elf = grub_elf_file (file, argv[0]);
  1247. if (elf)
  1248. {
  1249. is_elf_kernel = 1;
  1250. grub_bsd_load_elf (elf, argv[0]);
  1251. grub_elf_close (elf);
  1252. }
  1253. else
  1254. {
  1255. is_elf_kernel = 0;
  1256. grub_errno = 0;
  1257. grub_bsd_load_aout (file, argv[0]);
  1258. grub_file_close (file);
  1259. }
  1260. kern_end = ALIGN_PAGE (kern_end);
  1261. fail:
  1262. if (grub_errno != GRUB_ERR_NONE)
  1263. grub_dl_unref (my_mod);
  1264. return grub_errno;
  1265. }
  1266. static grub_uint32_t
  1267. grub_bsd_parse_flags (const struct grub_arg_list *state,
  1268. const grub_uint32_t * flags)
  1269. {
  1270. grub_uint32_t result = 0;
  1271. unsigned i;
  1272. for (i = 0; flags[i]; i++)
  1273. if (state[i].set)
  1274. result |= flags[i];
  1275. return result;
  1276. }
  1277. static grub_err_t
  1278. grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
  1279. {
  1280. kernel_type = KERNEL_TYPE_FREEBSD;
  1281. bootflags = grub_bsd_parse_flags (ctxt->state, freebsd_flags);
  1282. if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
  1283. {
  1284. grub_uint32_t unit, slice, part;
  1285. kern_end = ALIGN_PAGE (kern_end);
  1286. if (is_elf_kernel)
  1287. {
  1288. grub_err_t err;
  1289. grub_uint64_t data = 0;
  1290. grub_file_t file;
  1291. int len = is_64bit ? 8 : 4;
  1292. err = grub_freebsd_add_meta_module (argv[0], is_64bit
  1293. ? FREEBSD_MODTYPE_KERNEL64
  1294. : FREEBSD_MODTYPE_KERNEL,
  1295. argc - 1, argv + 1,
  1296. kern_start,
  1297. kern_end - kern_start);
  1298. if (err)
  1299. return err;
  1300. file = grub_file_open (argv[0], GRUB_FILE_TYPE_BSD_KERNEL);
  1301. if (! file)
  1302. return grub_errno;
  1303. if (is_64bit)
  1304. err = grub_freebsd_load_elf_meta64 (relocator, file, argv[0],
  1305. &kern_end);
  1306. else
  1307. err = grub_freebsd_load_elf_meta32 (relocator, file, argv[0],
  1308. &kern_end);
  1309. if (err)
  1310. return err;
  1311. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  1312. FREEBSD_MODINFOMD_HOWTO, &data, 4);
  1313. if (err)
  1314. return err;
  1315. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  1316. FREEBSD_MODINFOMD_ENVP, &data, len);
  1317. if (err)
  1318. return err;
  1319. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  1320. FREEBSD_MODINFOMD_KERNEND, &data, len);
  1321. if (err)
  1322. return err;
  1323. }
  1324. grub_bsd_get_device (&freebsd_biosdev, &unit, &slice, &part);
  1325. freebsd_zfsguid = 0;
  1326. if (!is_64bit)
  1327. freebsd_get_zfs ();
  1328. grub_print_error ();
  1329. freebsd_bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) +
  1330. (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT));
  1331. grub_loader_set (grub_freebsd_boot, grub_bsd_unload, 0);
  1332. }
  1333. return grub_errno;
  1334. }
  1335. static const char *types[] = {
  1336. [0] = "wd",
  1337. [2] = "fd",
  1338. [4] = "sd",
  1339. [6] = "cd",
  1340. [14] = "vnd",
  1341. [17] = "rd"
  1342. };
  1343. static grub_err_t
  1344. grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
  1345. {
  1346. grub_uint32_t bootdev;
  1347. kernel_type = KERNEL_TYPE_OPENBSD;
  1348. bootflags = grub_bsd_parse_flags (ctxt->state, openbsd_flags);
  1349. if (ctxt->state[OPENBSD_ROOT_ARG].set)
  1350. {
  1351. const char *arg = ctxt->state[OPENBSD_ROOT_ARG].arg;
  1352. unsigned type, unit, part;
  1353. for (type = 0; type < ARRAY_SIZE (types); type++)
  1354. if (types[type]
  1355. && grub_strncmp (arg, types[type],
  1356. grub_strlen (types[type])) == 0)
  1357. {
  1358. arg += grub_strlen (types[type]);
  1359. break;
  1360. }
  1361. if (type == ARRAY_SIZE (types))
  1362. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1363. "unknown disk type name");
  1364. unit = grub_strtoul (arg, (char **) &arg, 10);
  1365. if (! (arg && *arg >= 'a' && *arg <= 'z'))
  1366. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1367. "only device specifications of form "
  1368. "<type><number><lowercase letter> are supported");
  1369. part = *arg - 'a';
  1370. bootdev = (OPENBSD_B_DEVMAGIC | (type << OPENBSD_B_TYPESHIFT)
  1371. | (unit << OPENBSD_B_UNITSHIFT)
  1372. | (part << OPENBSD_B_PARTSHIFT));
  1373. }
  1374. else
  1375. bootdev = 0;
  1376. if (ctxt->state[OPENBSD_SERIAL_ARG].set)
  1377. {
  1378. struct grub_openbsd_bootarg_console serial;
  1379. char *ptr;
  1380. unsigned port = 0;
  1381. unsigned speed = 9600;
  1382. grub_memset (&serial, 0, sizeof (serial));
  1383. if (ctxt->state[OPENBSD_SERIAL_ARG].arg)
  1384. {
  1385. ptr = ctxt->state[OPENBSD_SERIAL_ARG].arg;
  1386. if (grub_memcmp (ptr, "com", sizeof ("com") - 1) != 0)
  1387. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1388. "only com0-com3 are supported");
  1389. ptr += sizeof ("com") - 1;
  1390. port = grub_strtoul (ptr, &ptr, 0);
  1391. if (port >= 4)
  1392. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1393. "only com0-com3 are supported");
  1394. if (*ptr == ',')
  1395. {
  1396. ptr++;
  1397. speed = grub_strtoul (ptr, &ptr, 0);
  1398. if (grub_errno)
  1399. return grub_errno;
  1400. }
  1401. }
  1402. serial.device = (GRUB_OPENBSD_COM_MAJOR << 8) | port;
  1403. serial.speed = speed;
  1404. serial.addr = grub_ns8250_hw_get_port (port);
  1405. grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial));
  1406. bootflags |= OPENBSD_RB_SERCONS;
  1407. }
  1408. else
  1409. {
  1410. struct grub_openbsd_bootarg_console serial;
  1411. grub_memset (&serial, 0, sizeof (serial));
  1412. serial.device = (GRUB_OPENBSD_VGA_MAJOR << 8);
  1413. serial.addr = 0xffffffff;
  1414. grub_bsd_add_meta (OPENBSD_BOOTARG_CONSOLE, &serial, sizeof (serial));
  1415. bootflags &= ~OPENBSD_RB_SERCONS;
  1416. }
  1417. if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
  1418. {
  1419. grub_loader_set (grub_openbsd_boot, grub_bsd_unload, 0);
  1420. openbsd_root = bootdev;
  1421. }
  1422. return grub_errno;
  1423. }
  1424. static grub_err_t
  1425. grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[])
  1426. {
  1427. grub_err_t err;
  1428. kernel_type = KERNEL_TYPE_NETBSD;
  1429. bootflags = grub_bsd_parse_flags (ctxt->state, netbsd_flags);
  1430. if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE)
  1431. {
  1432. if (is_elf_kernel)
  1433. {
  1434. grub_file_t file;
  1435. file = grub_file_open (argv[0], GRUB_FILE_TYPE_BSD_KERNEL);
  1436. if (! file)
  1437. return grub_errno;
  1438. if (is_64bit)
  1439. err = grub_netbsd_load_elf_meta64 (relocator, file, argv[0], &kern_end);
  1440. else
  1441. err = grub_netbsd_load_elf_meta32 (relocator, file, argv[0], &kern_end);
  1442. if (err)
  1443. return err;
  1444. }
  1445. {
  1446. char bootpath[GRUB_NETBSD_MAX_BOOTPATH_LEN];
  1447. char *name;
  1448. name = grub_strrchr (argv[0], '/');
  1449. if (name)
  1450. name++;
  1451. else
  1452. name = argv[0];
  1453. grub_memset (bootpath, 0, sizeof (bootpath));
  1454. grub_strncpy (bootpath, name, sizeof (bootpath) - 1);
  1455. grub_bsd_add_meta (NETBSD_BTINFO_BOOTPATH, bootpath, sizeof (bootpath));
  1456. }
  1457. if (ctxt->state[NETBSD_ROOT_ARG].set)
  1458. {
  1459. char root[GRUB_NETBSD_MAX_ROOTDEVICE_LEN];
  1460. grub_memset (root, 0, sizeof (root));
  1461. grub_strncpy (root, ctxt->state[NETBSD_ROOT_ARG].arg,
  1462. sizeof (root) - 1);
  1463. grub_bsd_add_meta (NETBSD_BTINFO_ROOTDEVICE, root, sizeof (root));
  1464. }
  1465. if (ctxt->state[NETBSD_SERIAL_ARG].set)
  1466. {
  1467. struct grub_netbsd_btinfo_serial serial;
  1468. char *ptr;
  1469. grub_memset (&serial, 0, sizeof (serial));
  1470. grub_strcpy (serial.devname, "com");
  1471. serial.addr = grub_ns8250_hw_get_port (0);
  1472. serial.speed = 9600;
  1473. if (ctxt->state[NETBSD_SERIAL_ARG].arg)
  1474. {
  1475. ptr = ctxt->state[NETBSD_SERIAL_ARG].arg;
  1476. if (grub_memcmp (ptr, "com", sizeof ("com") - 1) == 0)
  1477. {
  1478. ptr += sizeof ("com") - 1;
  1479. serial.addr
  1480. = grub_ns8250_hw_get_port (grub_strtoul (ptr, &ptr, 0));
  1481. }
  1482. else
  1483. serial.addr = grub_strtoul (ptr, &ptr, 0);
  1484. if (grub_errno)
  1485. return grub_errno;
  1486. if (*ptr == ',')
  1487. {
  1488. ptr++;
  1489. serial.speed = grub_strtoul (ptr, &ptr, 0);
  1490. if (grub_errno)
  1491. return grub_errno;
  1492. }
  1493. }
  1494. grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &serial, sizeof (serial));
  1495. }
  1496. else
  1497. {
  1498. struct grub_netbsd_btinfo_serial cons;
  1499. grub_memset (&cons, 0, sizeof (cons));
  1500. grub_strcpy (cons.devname, "pc");
  1501. grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &cons, sizeof (cons));
  1502. }
  1503. grub_netbsd_add_boot_disk_and_wedge ();
  1504. grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0);
  1505. }
  1506. return grub_errno;
  1507. }
  1508. static grub_err_t
  1509. grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)),
  1510. int argc, char *argv[])
  1511. {
  1512. grub_file_t file = 0;
  1513. char *buf = 0, *curr, *next;
  1514. int len;
  1515. if (! grub_loader_is_loaded ())
  1516. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1517. N_("you need to load the kernel first"));
  1518. if (kernel_type != KERNEL_TYPE_FREEBSD)
  1519. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1520. "only FreeBSD supports environment");
  1521. if (argc == 0)
  1522. {
  1523. grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  1524. goto fail;
  1525. }
  1526. file = grub_file_open (argv[0], GRUB_FILE_TYPE_FREEBSD_ENV);
  1527. if ((!file) || (!file->size))
  1528. goto fail;
  1529. len = file->size;
  1530. buf = grub_malloc (len + 1);
  1531. if (!buf)
  1532. goto fail;
  1533. if (grub_file_read (file, buf, len) != len)
  1534. goto fail;
  1535. buf[len] = 0;
  1536. next = buf;
  1537. while (next)
  1538. {
  1539. char *p;
  1540. curr = next;
  1541. next = grub_strchr (curr, '\n');
  1542. if (next)
  1543. {
  1544. p = next - 1;
  1545. while (p > curr)
  1546. {
  1547. if ((*p != '\r') && (*p != ' ') && (*p != '\t'))
  1548. break;
  1549. p--;
  1550. }
  1551. if ((p > curr) && (*p == '"'))
  1552. p--;
  1553. *(p + 1) = 0;
  1554. next++;
  1555. }
  1556. if (*curr == '#')
  1557. continue;
  1558. p = grub_strchr (curr, '=');
  1559. if (!p)
  1560. continue;
  1561. *(p++) = 0;
  1562. if (*curr)
  1563. {
  1564. char *name;
  1565. if (*p == '"')
  1566. p++;
  1567. name = grub_xasprintf ("kFreeBSD.%s", curr);
  1568. if (!name)
  1569. goto fail;
  1570. if (grub_env_set (name, p))
  1571. {
  1572. grub_free (name);
  1573. goto fail;
  1574. }
  1575. grub_free (name);
  1576. }
  1577. }
  1578. fail:
  1579. grub_free (buf);
  1580. if (file)
  1581. grub_file_close (file);
  1582. return grub_errno;
  1583. }
  1584. static grub_err_t
  1585. grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)),
  1586. int argc, char *argv[])
  1587. {
  1588. grub_file_t file = 0;
  1589. int modargc;
  1590. char **modargv;
  1591. const char *type;
  1592. grub_err_t err;
  1593. void *src;
  1594. if (! grub_loader_is_loaded ())
  1595. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1596. N_("you need to load the kernel first"));
  1597. if (kernel_type != KERNEL_TYPE_FREEBSD)
  1598. return grub_error (GRUB_ERR_BAD_ARGUMENT, "no FreeBSD loaded");
  1599. if (!is_elf_kernel)
  1600. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1601. "only ELF kernel supports module");
  1602. /* List the current modules if no parameter. */
  1603. if (!argc)
  1604. {
  1605. grub_freebsd_list_modules ();
  1606. return 0;
  1607. }
  1608. file = grub_file_open (argv[0], GRUB_FILE_TYPE_FREEBSD_MODULE);
  1609. if ((!file) || (!file->size))
  1610. goto fail;
  1611. {
  1612. grub_relocator_chunk_t ch;
  1613. err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_end,
  1614. file->size);
  1615. if (err)
  1616. goto fail;
  1617. src = get_virtual_current_address (ch);
  1618. }
  1619. grub_file_read (file, src, file->size);
  1620. if (grub_errno)
  1621. goto fail;
  1622. modargc = argc - 1;
  1623. modargv = argv + 1;
  1624. if (modargc && (! grub_memcmp (modargv[0], "type=", 5)))
  1625. {
  1626. type = &modargv[0][5];
  1627. modargc--;
  1628. modargv++;
  1629. }
  1630. else
  1631. type = FREEBSD_MODTYPE_RAW;
  1632. err = grub_freebsd_add_meta_module (argv[0], type, modargc, modargv,
  1633. kern_end, file->size);
  1634. if (err)
  1635. goto fail;
  1636. kern_end = ALIGN_PAGE (kern_end + file->size);
  1637. fail:
  1638. if (file)
  1639. grub_file_close (file);
  1640. return grub_errno;
  1641. }
  1642. static grub_err_t
  1643. grub_netbsd_module_load (char *filename, grub_uint32_t type)
  1644. {
  1645. grub_file_t file = 0;
  1646. void *src;
  1647. grub_err_t err;
  1648. file = grub_file_open (filename, GRUB_FILE_TYPE_NETBSD_MODULE);
  1649. if ((!file) || (!file->size))
  1650. goto fail;
  1651. {
  1652. grub_relocator_chunk_t ch;
  1653. err = grub_relocator_alloc_chunk_addr (relocator, &ch, kern_end,
  1654. file->size);
  1655. if (err)
  1656. goto fail;
  1657. src = get_virtual_current_address (ch);
  1658. }
  1659. grub_file_read (file, src, file->size);
  1660. if (grub_errno)
  1661. goto fail;
  1662. err = grub_netbsd_add_meta_module (filename, type, kern_end, file->size);
  1663. if (err)
  1664. goto fail;
  1665. kern_end = ALIGN_PAGE (kern_end + file->size);
  1666. fail:
  1667. if (file)
  1668. grub_file_close (file);
  1669. return grub_errno;
  1670. }
  1671. static grub_err_t
  1672. grub_cmd_netbsd_module (grub_command_t cmd,
  1673. int argc, char *argv[])
  1674. {
  1675. grub_uint32_t type;
  1676. if (! grub_loader_is_loaded ())
  1677. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1678. N_("you need to load the kernel first"));
  1679. if (kernel_type != KERNEL_TYPE_NETBSD)
  1680. return grub_error (GRUB_ERR_BAD_ARGUMENT, "no NetBSD loaded");
  1681. if (!is_elf_kernel)
  1682. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1683. "only ELF kernel supports module");
  1684. /* List the current modules if no parameter. */
  1685. if (!argc)
  1686. {
  1687. grub_netbsd_list_modules ();
  1688. return 0;
  1689. }
  1690. if (grub_strcmp (cmd->name, "knetbsd_module_elf") == 0)
  1691. type = GRUB_NETBSD_MODULE_ELF;
  1692. else
  1693. type = GRUB_NETBSD_MODULE_RAW;
  1694. return grub_netbsd_module_load (argv[0], type);
  1695. }
  1696. static grub_err_t
  1697. grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)),
  1698. int argc, char *argv[])
  1699. {
  1700. grub_file_t file = 0;
  1701. grub_err_t err;
  1702. if (! grub_loader_is_loaded ())
  1703. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1704. N_("you need to load the kernel first"));
  1705. if (kernel_type != KERNEL_TYPE_FREEBSD)
  1706. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1707. "only FreeBSD supports module");
  1708. if (! is_elf_kernel)
  1709. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1710. "only ELF kernel supports module");
  1711. /* List the current modules if no parameter. */
  1712. if (! argc)
  1713. {
  1714. grub_freebsd_list_modules ();
  1715. return 0;
  1716. }
  1717. file = grub_file_open (argv[0], GRUB_FILE_TYPE_FREEBSD_MODULE_ELF);
  1718. if (!file)
  1719. return grub_errno;
  1720. if (!file->size)
  1721. {
  1722. grub_file_close (file);
  1723. return grub_errno;
  1724. }
  1725. if (is_64bit)
  1726. err = grub_freebsd_load_elfmodule_obj64 (relocator, file,
  1727. argc, argv, &kern_end);
  1728. else
  1729. err = grub_freebsd_load_elfmodule32 (relocator, file,
  1730. argc, argv, &kern_end);
  1731. grub_file_close (file);
  1732. return err;
  1733. }
  1734. static grub_err_t
  1735. grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)),
  1736. int argc, char *args[])
  1737. {
  1738. grub_file_t file;
  1739. grub_size_t size;
  1740. if (argc != 1)
  1741. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  1742. if (! grub_loader_is_loaded ())
  1743. return grub_error (GRUB_ERR_BAD_ARGUMENT,
  1744. N_("you need to load the kernel first"));
  1745. if (kernel_type != KERNEL_TYPE_OPENBSD)
  1746. return grub_error (GRUB_ERR_BAD_OS, "no kOpenBSD loaded");
  1747. if (!openbsd_ramdisk.max_size)
  1748. return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD doesn't support ramdisk");
  1749. file = grub_file_open (args[0], GRUB_FILE_TYPE_OPENBSD_RAMDISK);
  1750. if (! file)
  1751. return grub_errno;
  1752. size = grub_file_size (file);
  1753. if (size > openbsd_ramdisk.max_size)
  1754. {
  1755. grub_file_close (file);
  1756. return grub_error (GRUB_ERR_BAD_OS, "your kOpenBSD supports ramdisk only"
  1757. " up to %u bytes, however you supplied a %u bytes one",
  1758. openbsd_ramdisk.max_size, size);
  1759. }
  1760. if (grub_file_read (file, openbsd_ramdisk.target, size)
  1761. != (grub_ssize_t) (size))
  1762. {
  1763. grub_file_close (file);
  1764. if (!grub_errno)
  1765. grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), args[0]);
  1766. return grub_errno;
  1767. }
  1768. grub_memset (openbsd_ramdisk.target + size, 0,
  1769. openbsd_ramdisk.max_size - size);
  1770. *openbsd_ramdisk.size = ALIGN_UP (size, 512);
  1771. return GRUB_ERR_NONE;
  1772. }
  1773. static grub_extcmd_t cmd_freebsd, cmd_openbsd, cmd_netbsd;
  1774. static grub_command_t cmd_freebsd_loadenv, cmd_freebsd_module;
  1775. static grub_command_t cmd_netbsd_module, cmd_freebsd_module_elf;
  1776. static grub_command_t cmd_netbsd_module_elf, cmd_openbsd_ramdisk;
  1777. GRUB_MOD_INIT (bsd)
  1778. {
  1779. /* Net and OpenBSD kernels are often compressed. */
  1780. grub_dl_load ("gzio");
  1781. cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, 0,
  1782. N_("FILE"), N_("Load kernel of FreeBSD."),
  1783. freebsd_opts);
  1784. cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, 0,
  1785. N_("FILE"), N_("Load kernel of OpenBSD."),
  1786. openbsd_opts);
  1787. cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, 0,
  1788. N_("FILE"), N_("Load kernel of NetBSD."),
  1789. netbsd_opts);
  1790. cmd_freebsd_loadenv =
  1791. grub_register_command ("kfreebsd_loadenv", grub_cmd_freebsd_loadenv,
  1792. 0, N_("Load FreeBSD env."));
  1793. cmd_freebsd_module =
  1794. grub_register_command ("kfreebsd_module", grub_cmd_freebsd_module,
  1795. 0, N_("Load FreeBSD kernel module."));
  1796. cmd_netbsd_module =
  1797. grub_register_command ("knetbsd_module", grub_cmd_netbsd_module,
  1798. 0, N_("Load NetBSD kernel module."));
  1799. cmd_netbsd_module_elf =
  1800. grub_register_command ("knetbsd_module_elf", grub_cmd_netbsd_module,
  1801. 0, N_("Load NetBSD kernel module (ELF)."));
  1802. cmd_freebsd_module_elf =
  1803. grub_register_command ("kfreebsd_module_elf", grub_cmd_freebsd_module_elf,
  1804. 0, N_("Load FreeBSD kernel module (ELF)."));
  1805. cmd_openbsd_ramdisk = grub_register_command ("kopenbsd_ramdisk",
  1806. grub_cmd_openbsd_ramdisk, 0,
  1807. /* TRANSLATORS: ramdisk isn't identifier,
  1808. it can be translated. */
  1809. N_("Load kOpenBSD ramdisk."));
  1810. my_mod = mod;
  1811. }
  1812. GRUB_MOD_FINI (bsd)
  1813. {
  1814. grub_unregister_extcmd (cmd_freebsd);
  1815. grub_unregister_extcmd (cmd_openbsd);
  1816. grub_unregister_extcmd (cmd_netbsd);
  1817. grub_unregister_command (cmd_freebsd_loadenv);
  1818. grub_unregister_command (cmd_freebsd_module);
  1819. grub_unregister_command (cmd_netbsd_module);
  1820. grub_unregister_command (cmd_freebsd_module_elf);
  1821. grub_unregister_command (cmd_netbsd_module_elf);
  1822. grub_unregister_command (cmd_openbsd_ramdisk);
  1823. grub_bsd_unload ();
  1824. }