syslinux_parse.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2013 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/mm.h>
  19. #include <grub/file.h>
  20. #include <grub/normal.h>
  21. #include <grub/syslinux_parse.h>
  22. struct syslinux_say
  23. {
  24. struct syslinux_say *next;
  25. struct syslinux_say *prev;
  26. char msg[0];
  27. };
  28. struct initrd_list
  29. {
  30. struct initrd_list *next;
  31. char *file;
  32. };
  33. struct syslinux_menuentry
  34. {
  35. struct syslinux_menuentry *next;
  36. struct syslinux_menuentry *prev;
  37. char *label;
  38. char *extlabel;
  39. char *kernel_file;
  40. struct initrd_list *initrds;
  41. struct initrd_list *initrds_last;
  42. char *append;
  43. char *argument;
  44. char *help;
  45. char *comments;
  46. grub_size_t commentslen;
  47. char hotkey;
  48. int make_default;
  49. struct syslinux_say *say;
  50. enum { KERNEL_NO_KERNEL, KERNEL_LINUX, KERNEL_CHAINLOADER,
  51. KERNEL_BIN, KERNEL_PXE, KERNEL_CHAINLOADER_BPB,
  52. KERNEL_COM32, KERNEL_COM, KERNEL_IMG, KERNEL_CONFIG, LOCALBOOT }
  53. entry_type;
  54. };
  55. struct syslinux_menu
  56. {
  57. struct syslinux_menu *parent;
  58. struct syslinux_menuentry *entries;
  59. char *def;
  60. char *comments;
  61. char *background;
  62. const char *root_read_directory;
  63. const char *root_target_directory;
  64. const char *current_read_directory;
  65. const char *current_target_directory;
  66. const char *filename;
  67. grub_size_t commentslen;
  68. unsigned long timeout;
  69. struct syslinux_say *say;
  70. grub_syslinux_flavour_t flavour;
  71. };
  72. struct output_buffer
  73. {
  74. grub_size_t alloc;
  75. grub_size_t ptr;
  76. char *buf;
  77. };
  78. static grub_err_t
  79. syslinux_parse_real (struct syslinux_menu *menu);
  80. static grub_err_t
  81. config_file (struct output_buffer *outbuf,
  82. const char *root, const char *target_root,
  83. const char *cwd, const char *target_cwd,
  84. const char *fname, struct syslinux_menu *parent,
  85. grub_syslinux_flavour_t flav);
  86. static grub_err_t
  87. print_entry (struct output_buffer *outbuf,
  88. struct syslinux_menu *menu,
  89. const char *str);
  90. static grub_err_t
  91. ensure_space (struct output_buffer *outbuf, grub_size_t len)
  92. {
  93. grub_size_t newlen;
  94. char *newbuf;
  95. if (len < outbuf->alloc - outbuf->ptr)
  96. return GRUB_ERR_NONE;
  97. newlen = (outbuf->ptr + len + 10) * 2;
  98. newbuf = grub_realloc (outbuf->buf, newlen);
  99. if (!newbuf)
  100. return grub_errno;
  101. outbuf->alloc = newlen;
  102. outbuf->buf = newbuf;
  103. return GRUB_ERR_NONE;
  104. }
  105. static grub_err_t
  106. print (struct output_buffer *outbuf, const char *str, grub_size_t len)
  107. {
  108. grub_err_t err;
  109. err = ensure_space (outbuf, len);
  110. if (err)
  111. return err;
  112. grub_memcpy (&outbuf->buf[outbuf->ptr], str, len);
  113. outbuf->ptr += len;
  114. return GRUB_ERR_NONE;
  115. }
  116. static grub_err_t
  117. add_comment (struct syslinux_menu *menu, const char *comment, int nl)
  118. {
  119. if (menu->entries)
  120. {
  121. if (menu->entries->commentslen == 0 && *comment == 0)
  122. return GRUB_ERR_NONE;
  123. menu->entries->comments = grub_realloc (menu->entries->comments,
  124. menu->entries->commentslen
  125. + 2 + grub_strlen (comment));
  126. if (!menu->entries->comments)
  127. return grub_errno;
  128. menu->entries->commentslen
  129. += grub_stpcpy (menu->entries->comments + menu->entries->commentslen,
  130. comment)
  131. - (menu->entries->comments + menu->entries->commentslen);
  132. if (nl)
  133. menu->entries->comments[menu->entries->commentslen++] = '\n';
  134. menu->entries->comments[menu->entries->commentslen] = '\0';
  135. }
  136. else
  137. {
  138. if (menu->commentslen == 0 && *comment == 0)
  139. return GRUB_ERR_NONE;
  140. menu->comments = grub_realloc (menu->comments, menu->commentslen
  141. + 2 + grub_strlen (comment));
  142. if (!menu->comments)
  143. return grub_errno;
  144. menu->commentslen += grub_stpcpy (menu->comments + menu->commentslen,
  145. comment)
  146. - (menu->comments + menu->commentslen);
  147. if (nl)
  148. menu->comments[menu->commentslen++] = '\n';
  149. menu->comments[menu->commentslen] = '\0';
  150. }
  151. return GRUB_ERR_NONE;
  152. }
  153. #define print_string(x) do { err = print (outbuf, x, sizeof (x) - 1); if (err) return err; } while (0)
  154. static grub_err_t
  155. print_num (struct output_buffer *outbuf, int n)
  156. {
  157. char buf[20];
  158. grub_snprintf (buf, sizeof (buf), "%d", n);
  159. return print (outbuf, buf, grub_strlen (buf));
  160. }
  161. static grub_err_t
  162. label (const char *line, struct syslinux_menu *menu)
  163. {
  164. struct syslinux_menuentry *entry;
  165. entry = grub_malloc (sizeof (*entry));
  166. if (!entry)
  167. return grub_errno;
  168. grub_memset (entry, 0, sizeof (*entry));
  169. entry->label = grub_strdup (line);
  170. if (!entry->label)
  171. {
  172. grub_free (entry);
  173. return grub_errno;
  174. }
  175. entry->next = menu->entries;
  176. entry->prev = NULL;
  177. if (menu->entries)
  178. menu->entries->prev = entry;
  179. menu->entries = entry;
  180. return GRUB_ERR_NONE;
  181. }
  182. static grub_err_t
  183. kernel (const char *line, struct syslinux_menu *menu)
  184. {
  185. const char *end = line + grub_strlen (line);
  186. if (!menu->entries)
  187. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  188. menu->entries->kernel_file = grub_strdup (line);
  189. if (!menu->entries->kernel_file)
  190. return grub_errno;
  191. menu->entries->entry_type = KERNEL_LINUX;
  192. if (end - line >= 2 && grub_strcmp (end - 2, ".0") == 0)
  193. menu->entries->entry_type = KERNEL_PXE;
  194. if (end - line >= 4 && grub_strcasecmp (end - 4, ".bin") == 0)
  195. menu->entries->entry_type = KERNEL_BIN;
  196. if (end - line >= 3 && grub_strcasecmp (end - 3, ".bs") == 0)
  197. menu->entries->entry_type = KERNEL_CHAINLOADER;
  198. if (end - line >= 4 && grub_strcasecmp (end - 4, ".bss") == 0)
  199. menu->entries->entry_type = KERNEL_CHAINLOADER_BPB;
  200. if (end - line >= 4 && grub_strcasecmp (end - 4, ".c32") == 0)
  201. menu->entries->entry_type = KERNEL_COM32;
  202. if (end - line >= 4 && grub_strcasecmp (end - 4, ".cbt") == 0)
  203. menu->entries->entry_type = KERNEL_COM;
  204. if (end - line >= 4 && grub_strcasecmp (end - 4, ".com") == 0)
  205. menu->entries->entry_type = KERNEL_COM;
  206. if (end - line >= 4 && grub_strcasecmp (end - 4, ".img") == 0)
  207. menu->entries->entry_type = KERNEL_IMG;
  208. return GRUB_ERR_NONE;
  209. }
  210. static grub_err_t
  211. cmd_linux (const char *line, struct syslinux_menu *menu)
  212. {
  213. if (!menu->entries)
  214. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  215. menu->entries->kernel_file = grub_strdup (line);
  216. if (!menu->entries->kernel_file)
  217. return grub_errno;
  218. menu->entries->entry_type = KERNEL_LINUX;
  219. return GRUB_ERR_NONE;
  220. }
  221. static grub_err_t
  222. cmd_boot (const char *line, struct syslinux_menu *menu)
  223. {
  224. if (!menu->entries)
  225. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  226. menu->entries->kernel_file = grub_strdup (line);
  227. if (!menu->entries->kernel_file)
  228. return grub_errno;
  229. menu->entries->entry_type = KERNEL_CHAINLOADER;
  230. return GRUB_ERR_NONE;
  231. }
  232. static grub_err_t
  233. cmd_bss (const char *line, struct syslinux_menu *menu)
  234. {
  235. if (!menu->entries)
  236. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  237. menu->entries->kernel_file = grub_strdup (line);
  238. if (!menu->entries->kernel_file)
  239. return grub_errno;
  240. menu->entries->entry_type = KERNEL_CHAINLOADER_BPB;
  241. return GRUB_ERR_NONE;
  242. }
  243. static grub_err_t
  244. cmd_pxe (const char *line, struct syslinux_menu *menu)
  245. {
  246. if (!menu->entries)
  247. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  248. menu->entries->kernel_file = grub_strdup (line);
  249. if (!menu->entries->kernel_file)
  250. return grub_errno;
  251. menu->entries->entry_type = KERNEL_PXE;
  252. return GRUB_ERR_NONE;
  253. }
  254. static grub_err_t
  255. cmd_fdimage (const char *line, struct syslinux_menu *menu)
  256. {
  257. if (!menu->entries)
  258. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  259. menu->entries->kernel_file = grub_strdup (line);
  260. if (!menu->entries->kernel_file)
  261. return grub_errno;
  262. menu->entries->entry_type = KERNEL_IMG;
  263. return GRUB_ERR_NONE;
  264. }
  265. static grub_err_t
  266. cmd_comboot (const char *line, struct syslinux_menu *menu)
  267. {
  268. if (!menu->entries)
  269. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  270. menu->entries->kernel_file = grub_strdup (line);
  271. if (!menu->entries->kernel_file)
  272. return grub_errno;
  273. menu->entries->entry_type = KERNEL_COM;
  274. return GRUB_ERR_NONE;
  275. }
  276. static grub_err_t
  277. cmd_com32 (const char *line, struct syslinux_menu *menu)
  278. {
  279. if (!menu->entries)
  280. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  281. menu->entries->kernel_file = grub_strdup (line);
  282. if (!menu->entries->kernel_file)
  283. return grub_errno;
  284. menu->entries->entry_type = KERNEL_COM32;
  285. return GRUB_ERR_NONE;
  286. }
  287. static grub_err_t
  288. cmd_config (const char *line, struct syslinux_menu *menu)
  289. {
  290. const char *space;
  291. if (!menu->entries)
  292. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  293. for (space = line; *space && !grub_isspace (*space); space++);
  294. menu->entries->kernel_file = grub_strndup (line, space - line);
  295. if (!menu->entries->kernel_file)
  296. return grub_errno;
  297. for (; *space && grub_isspace (*space); space++);
  298. if (*space)
  299. {
  300. menu->entries->argument = grub_strdup (space);
  301. if (!menu->entries->argument)
  302. return grub_errno;
  303. }
  304. menu->entries->entry_type = KERNEL_CONFIG;
  305. return GRUB_ERR_NONE;
  306. }
  307. static grub_err_t
  308. cmd_append (const char *line, struct syslinux_menu *menu)
  309. {
  310. if (!menu->entries)
  311. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  312. menu->entries->append = grub_strdup (line);
  313. if (!menu->entries->append)
  314. return grub_errno;
  315. return GRUB_ERR_NONE;
  316. }
  317. static grub_err_t
  318. cmd_initrd (const char *line, struct syslinux_menu *menu)
  319. {
  320. struct initrd_list *ninitrd;
  321. const char *comma;
  322. if (!menu->entries)
  323. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  324. while (*line)
  325. {
  326. for (comma = line; *comma && *comma != ','; comma++);
  327. ninitrd = grub_malloc (sizeof (*ninitrd));
  328. if (!ninitrd)
  329. return grub_errno;
  330. ninitrd->file = grub_strndup (line, comma - line);
  331. if (!ninitrd->file)
  332. {
  333. grub_free (ninitrd);
  334. return grub_errno;
  335. }
  336. ninitrd->next = NULL;
  337. if (menu->entries->initrds_last)
  338. menu->entries->initrds_last->next = ninitrd;
  339. else
  340. {
  341. menu->entries->initrds_last = ninitrd;
  342. menu->entries->initrds = ninitrd;
  343. }
  344. line = comma;
  345. while (*line == ',')
  346. line++;
  347. }
  348. return GRUB_ERR_NONE;
  349. }
  350. static grub_err_t
  351. cmd_default (const char *line, struct syslinux_menu *menu)
  352. {
  353. menu->def = grub_strdup (line);
  354. if (!menu->def)
  355. return grub_errno;
  356. return GRUB_ERR_NONE;
  357. }
  358. static grub_err_t
  359. cmd_timeout (const char *line, struct syslinux_menu *menu)
  360. {
  361. menu->timeout = grub_strtoul (line, NULL, 0);
  362. return GRUB_ERR_NONE;
  363. }
  364. static grub_err_t
  365. cmd_menudefault (const char *line __attribute__ ((unused)),
  366. struct syslinux_menu *menu)
  367. {
  368. if (!menu->entries)
  369. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  370. menu->entries->make_default = 1;
  371. return GRUB_ERR_NONE;
  372. }
  373. static grub_err_t
  374. cmd_menubackground (const char *line,
  375. struct syslinux_menu *menu)
  376. {
  377. menu->background = grub_strdup (line);
  378. return GRUB_ERR_NONE;
  379. }
  380. static grub_err_t
  381. cmd_localboot (const char *line,
  382. struct syslinux_menu *menu)
  383. {
  384. if (!menu->entries)
  385. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  386. menu->entries->kernel_file = grub_strdup (line);
  387. if (!menu->entries->kernel_file)
  388. return grub_errno;
  389. menu->entries->entry_type = LOCALBOOT;
  390. return GRUB_ERR_NONE;
  391. }
  392. static grub_err_t
  393. cmd_extlabel (const char *line, struct syslinux_menu *menu)
  394. {
  395. const char *in;
  396. char *out;
  397. if (!menu->entries)
  398. return grub_error (GRUB_ERR_BAD_ARGUMENT, "kernel without label");
  399. menu->entries->extlabel = grub_malloc (grub_strlen (line) + 1);
  400. if (!menu->entries->extlabel)
  401. return grub_errno;
  402. in = line;
  403. out = menu->entries->extlabel;
  404. while (*in)
  405. {
  406. if (in[0] == '^' && in[1])
  407. {
  408. menu->entries->hotkey = grub_tolower (in[1]);
  409. in++;
  410. }
  411. *out++ = *in++;
  412. }
  413. *out = 0;
  414. return GRUB_ERR_NONE;
  415. }
  416. static grub_err_t
  417. cmd_say (const char *line, struct syslinux_menu *menu)
  418. {
  419. struct syslinux_say *nsay;
  420. nsay = grub_malloc (sizeof (*nsay) + grub_strlen (line) + 1);
  421. if (!nsay)
  422. return grub_errno;
  423. nsay->prev = NULL;
  424. if (menu->entries)
  425. {
  426. nsay->next = menu->entries->say;
  427. menu->entries->say = nsay;
  428. }
  429. else
  430. {
  431. nsay->next = menu->say;
  432. menu->say = nsay;
  433. }
  434. if (nsay->next)
  435. nsay->next->prev = nsay;
  436. grub_memcpy (nsay->msg, line, grub_strlen (line) + 1);
  437. return GRUB_ERR_NONE;
  438. }
  439. static char *
  440. get_read_filename (struct syslinux_menu *menu,
  441. const char *filename)
  442. {
  443. return grub_xasprintf ("%s/%s",
  444. filename[0] == '/' ? menu->root_read_directory
  445. : menu->current_read_directory, filename);
  446. }
  447. static char *
  448. get_target_filename (struct syslinux_menu *menu,
  449. const char *filename)
  450. {
  451. return grub_xasprintf ("%s/%s",
  452. filename[0] == '/' ? menu->root_target_directory
  453. : menu->current_target_directory, filename);
  454. }
  455. static grub_err_t
  456. syslinux_parse (const char *filename,
  457. struct syslinux_menu *menu)
  458. {
  459. const char *old_filename = menu->filename;
  460. grub_err_t ret;
  461. char *nf;
  462. nf = get_read_filename (menu, filename);
  463. if (!nf)
  464. return grub_errno;
  465. menu->filename = nf;
  466. ret = syslinux_parse_real (menu);
  467. if (ret == GRUB_ERR_FILE_NOT_FOUND
  468. || ret == GRUB_ERR_BAD_FILENAME)
  469. {
  470. grub_errno = ret = GRUB_ERR_NONE;
  471. add_comment (menu, "# File ", 0);
  472. add_comment (menu, nf, 0);
  473. add_comment (menu, " not found", 1);
  474. }
  475. grub_free (nf);
  476. menu->filename = old_filename;
  477. return ret;
  478. }
  479. struct
  480. {
  481. const char *name1;
  482. const char *name2;
  483. grub_err_t (*parse) (const char *line, struct syslinux_menu *menu);
  484. } commands[] = {
  485. /* FIXME: support tagname. */
  486. {"include", NULL, syslinux_parse},
  487. {"menu", "include", syslinux_parse},
  488. {"label", NULL, label},
  489. {"kernel", NULL, kernel},
  490. {"linux", NULL, cmd_linux},
  491. {"boot", NULL, cmd_boot},
  492. {"bss", NULL, cmd_bss},
  493. {"pxe", NULL, cmd_pxe},
  494. {"fdimage", NULL, cmd_fdimage},
  495. {"comboot", NULL, cmd_comboot},
  496. {"com32", NULL, cmd_com32},
  497. {"config", NULL, cmd_config},
  498. {"append", NULL, cmd_append},
  499. /* FIXME: ipappend not supported. */
  500. {"localboot", NULL, cmd_localboot},
  501. {"initrd", NULL, cmd_initrd},
  502. {"default", NULL, cmd_default},
  503. {"menu", "label", cmd_extlabel},
  504. /* FIXME: MENU LABEL not supported. */
  505. /* FIXME: MENU HIDDEN not supported. */
  506. /* FIXME: MENU SEPARATOR not supported. */
  507. /* FIXME: MENU INDENT not supported. */
  508. /* FIXME: MENU DISABLE not supported. */
  509. /* FIXME: MENU HIDE not supported. */
  510. {"menu", "default", cmd_menudefault},
  511. /* FIXME: MENU PASSWD not supported. */
  512. /* FIXME: MENU MASTER PASSWD not supported. */
  513. {"menu", "background", cmd_menubackground},
  514. /* FIXME: MENU BEGIN not supported. */
  515. /* FIXME: MENU GOTO not supported. */
  516. /* FIXME: MENU EXIT not supported. */
  517. /* FIXME: MENU QUIT not supported. */
  518. /* FIXME: MENU START not supported. */
  519. /* FIXME: MENU AUTOBOOT not supported. */
  520. /* FIXME: MENU TABMSG not supported. */
  521. /* FIXME: MENU NOTABMSG not supported. */
  522. /* FIXME: MENU PASSPROMPT not supported. */
  523. /* FIXME: MENU COLOR not supported. */
  524. /* FIXME: MENU MSGCOLOR not supported. */
  525. /* FIXME: MENU WIDTH not supported. */
  526. /* FIXME: MENU MARGIN not supported. */
  527. /* FIXME: MENU PASSWORDMARGIN not supported. */
  528. /* FIXME: MENU ROWS not supported. */
  529. /* FIXME: MENU TABMSGROW not supported. */
  530. /* FIXME: MENU CMDLINEROW not supported. */
  531. /* FIXME: MENU ENDROW not supported. */
  532. /* FIXME: MENU PASSWORDROW not supported. */
  533. /* FIXME: MENU TIMEOUTROW not supported. */
  534. /* FIXME: MENU HELPMSGROW not supported. */
  535. /* FIXME: MENU HELPMSGENDROW not supported. */
  536. /* FIXME: MENU HIDDENROW not supported. */
  537. /* FIXME: MENU HSHIFT not supported. */
  538. /* FIXME: MENU VSHIFT not supported. */
  539. {"timeout", NULL, cmd_timeout},
  540. /* FIXME: TOTALTIMEOUT not supported. */
  541. /* FIXME: ONTIMEOUT not supported. */
  542. /* FIXME: ONERROR not supported. */
  543. /* FIXME: SERIAL not supported. */
  544. /* FIXME: CONSOLE not supported. */
  545. /* FIXME: FONT not supported. */
  546. /* FIXME: KBDMAP not supported. */
  547. {"say", NULL, cmd_say},
  548. /* FIXME: DISPLAY not supported. */
  549. /* FIXME: F* not supported. */
  550. /* Commands to control interface behaviour which aren't needed with GRUB.
  551. If they are important in your environment please contact GRUB team.
  552. */
  553. {"prompt", NULL, NULL},
  554. {"nocomplete", NULL, NULL},
  555. {"noescape", NULL, NULL},
  556. {"implicit", NULL, NULL},
  557. {"allowoptions", NULL, NULL}
  558. };
  559. static grub_err_t
  560. helptext (const char *line, grub_file_t file, struct syslinux_menu *menu)
  561. {
  562. char *help;
  563. char *buf = NULL;
  564. grub_size_t helplen, alloclen = 0;
  565. help = grub_strdup (line);
  566. if (!help)
  567. return grub_errno;
  568. helplen = grub_strlen (line);
  569. while ((grub_free (buf), buf = grub_file_getline (file)))
  570. {
  571. char *ptr;
  572. grub_size_t needlen;
  573. for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
  574. if (grub_strncasecmp (ptr, "endtext", sizeof ("endtext") - 1) == 0)
  575. {
  576. ptr += sizeof ("endtext") - 1;
  577. for (; *ptr && (grub_isspace (*ptr) || *ptr == '\n' || *ptr == '\r');
  578. ptr++);
  579. if (!*ptr)
  580. {
  581. menu->entries->help = help;
  582. grub_free (buf);
  583. return GRUB_ERR_NONE;
  584. }
  585. }
  586. needlen = helplen + 1 + grub_strlen (buf);
  587. if (alloclen < needlen)
  588. {
  589. alloclen = 2 * needlen;
  590. help = grub_realloc (help, alloclen);
  591. if (!help)
  592. {
  593. grub_free (buf);
  594. return grub_errno;
  595. }
  596. }
  597. helplen += grub_stpcpy (help + helplen, buf) - (help + helplen);
  598. }
  599. grub_free (buf);
  600. grub_free (help);
  601. return grub_errno;
  602. }
  603. static grub_err_t
  604. syslinux_parse_real (struct syslinux_menu *menu)
  605. {
  606. grub_file_t file;
  607. char *buf = NULL;
  608. grub_err_t err = GRUB_ERR_NONE;
  609. file = grub_file_open (menu->filename, GRUB_FILE_TYPE_CONFIG);
  610. if (!file)
  611. return grub_errno;
  612. while ((grub_free (buf), buf = grub_file_getline (file)))
  613. {
  614. const char *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
  615. char *end;
  616. unsigned i;
  617. end = buf + grub_strlen (buf);
  618. while (end > buf && (end[-1] == '\n' || end[-1] == '\r'))
  619. end--;
  620. *end = 0;
  621. for (ptr1 = buf; *ptr1 && grub_isspace (*ptr1); ptr1++);
  622. if (*ptr1 == '#' || *ptr1 == 0)
  623. {
  624. err = add_comment (menu, ptr1, 1);
  625. if (err)
  626. goto fail;
  627. continue;
  628. }
  629. for (ptr2 = ptr1; !grub_isspace (*ptr2) && *ptr2; ptr2++);
  630. for (ptr3 = ptr2; grub_isspace (*ptr3) && *ptr3; ptr3++);
  631. for (ptr4 = ptr3; !grub_isspace (*ptr4) && *ptr4; ptr4++);
  632. for (ptr5 = ptr4; grub_isspace (*ptr5) && *ptr5; ptr5++);
  633. for (i = 0; i < ARRAY_SIZE(commands); i++)
  634. if (grub_strlen (commands[i].name1) == (grub_size_t) (ptr2 - ptr1)
  635. && grub_strncasecmp (commands[i].name1, ptr1, ptr2 - ptr1) == 0
  636. && (commands[i].name2 == NULL
  637. || (grub_strlen (commands[i].name2)
  638. == (grub_size_t) (ptr4 - ptr3)
  639. && grub_strncasecmp (commands[i].name2, ptr3, ptr4 - ptr3)
  640. == 0)))
  641. break;
  642. if (i == ARRAY_SIZE(commands))
  643. {
  644. if (sizeof ("text") - 1 == ptr2 - ptr1
  645. && grub_strncasecmp ("text", ptr1, ptr2 - ptr1) == 0
  646. && (sizeof ("help") - 1 == ptr4 - ptr3
  647. && grub_strncasecmp ("help", ptr3, ptr4 - ptr3) == 0))
  648. {
  649. if (helptext (ptr5, file, menu))
  650. {
  651. grub_free (buf);
  652. return 1;
  653. }
  654. continue;
  655. }
  656. add_comment (menu, " # UNSUPPORTED command '", 0);
  657. add_comment (menu, ptr1, 0);
  658. add_comment (menu, "'", 1);
  659. continue;
  660. }
  661. if (commands[i].parse)
  662. {
  663. err = commands[i].parse (commands[i].name2
  664. ? ptr5 : ptr3, menu);
  665. if (err)
  666. goto fail;
  667. }
  668. }
  669. fail:
  670. grub_file_close (file);
  671. grub_free (buf);
  672. return err;
  673. }
  674. static grub_err_t
  675. print_escaped (struct output_buffer *outbuf,
  676. const char *from, const char *to)
  677. {
  678. const char *ptr;
  679. grub_err_t err;
  680. if (!to)
  681. to = from + grub_strlen (from);
  682. err = ensure_space (outbuf, (to - from) * 4 + 2);
  683. if (err)
  684. return err;
  685. outbuf->buf[outbuf->ptr++] = '\'';
  686. for (ptr = from; *ptr && ptr < to; ptr++)
  687. {
  688. if (*ptr == '\'')
  689. {
  690. outbuf->buf[outbuf->ptr++] = '\'';
  691. outbuf->buf[outbuf->ptr++] = '\\';
  692. outbuf->buf[outbuf->ptr++] = '\'';
  693. outbuf->buf[outbuf->ptr++] = '\'';
  694. }
  695. else
  696. outbuf->buf[outbuf->ptr++] = *ptr;
  697. }
  698. outbuf->buf[outbuf->ptr++] = '\'';
  699. return GRUB_ERR_NONE;
  700. }
  701. static grub_err_t
  702. print_file (struct output_buffer *outbuf,
  703. struct syslinux_menu *menu, const char *from, const char *to)
  704. {
  705. grub_err_t err;
  706. if (!to)
  707. to = from + grub_strlen (from);
  708. err = print_escaped (outbuf, from[0] == '/'
  709. ? menu->root_target_directory
  710. : menu->current_target_directory, NULL);
  711. if (err)
  712. return err;
  713. err = print (outbuf, "/", 1);
  714. if (err)
  715. return err;
  716. return print_escaped (outbuf, from, to);
  717. }
  718. /*
  719. * Makefile.am mimics this when generating tests/syslinux/ubuntu10.04_grub.cfg,
  720. * so changes here may need to be reflected there too.
  721. */
  722. static void
  723. simplify_filename (char *str)
  724. {
  725. char *iptr, *optr = str;
  726. for (iptr = str; *iptr; iptr++)
  727. {
  728. if (*iptr == '/' && optr != str && optr[-1] == '/')
  729. continue;
  730. if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '/')
  731. {
  732. iptr += 2;
  733. continue;
  734. }
  735. if (iptr[0] == '/' && iptr[1] == '.' && iptr[2] == '.'
  736. && iptr[3] == '/')
  737. {
  738. iptr += 3;
  739. while (optr >= str && *optr != '/')
  740. optr--;
  741. if (optr < str)
  742. {
  743. str[0] = '/';
  744. optr = str;
  745. }
  746. optr++;
  747. continue;
  748. }
  749. *optr++ = *iptr;
  750. }
  751. *optr = '\0';
  752. }
  753. static grub_err_t
  754. print_config (struct output_buffer *outbuf,
  755. struct syslinux_menu *menu,
  756. const char *filename, const char *basedir)
  757. {
  758. struct syslinux_menu *menuptr;
  759. grub_err_t err = GRUB_ERR_NONE;
  760. char *new_cwd = NULL;
  761. char *new_target_cwd = NULL;
  762. char *newname = NULL;
  763. int depth = 0;
  764. new_cwd = get_read_filename (menu, basedir);
  765. if (!new_cwd)
  766. {
  767. err = grub_errno;
  768. goto out;
  769. }
  770. new_target_cwd = get_target_filename (menu, basedir);
  771. if (!new_target_cwd)
  772. {
  773. err = grub_errno;
  774. goto out;
  775. }
  776. newname = get_read_filename (menu, filename);
  777. if (!newname)
  778. {
  779. err = grub_errno;
  780. goto out;
  781. }
  782. simplify_filename (newname);
  783. print_string ("#");
  784. print_file (outbuf, menu, filename, NULL);
  785. print_string (" ");
  786. err = print (outbuf, newname, grub_strlen (newname));
  787. if (err)
  788. return err;
  789. print_string (":\n");
  790. for (menuptr = menu; menuptr; menuptr = menuptr->parent, depth++)
  791. if (grub_strcmp (menuptr->filename, newname) == 0
  792. || depth > 20)
  793. break;
  794. if (menuptr)
  795. {
  796. print_string (" syslinux_configfile -r ");
  797. print_file (outbuf, menu, "/", NULL);
  798. print_string (" -c ");
  799. print_file (outbuf, menu, basedir, NULL);
  800. print_string (" ");
  801. print_file (outbuf, menu, filename, NULL);
  802. print_string ("\n");
  803. }
  804. else
  805. {
  806. err = config_file (outbuf, menu->root_read_directory,
  807. menu->root_target_directory, new_cwd, new_target_cwd,
  808. newname, menu, menu->flavour);
  809. if (err == GRUB_ERR_FILE_NOT_FOUND
  810. || err == GRUB_ERR_BAD_FILENAME)
  811. {
  812. grub_errno = err = GRUB_ERR_NONE;
  813. print_string ("# File ");
  814. err = print (outbuf, newname, grub_strlen (newname));
  815. if (err)
  816. goto out;
  817. print_string (" not found\n");
  818. }
  819. }
  820. out:
  821. grub_free (newname);
  822. grub_free (new_cwd);
  823. grub_free (new_target_cwd);
  824. return err;
  825. }
  826. static grub_err_t
  827. write_entry (struct output_buffer *outbuf,
  828. struct syslinux_menu *menu,
  829. struct syslinux_menuentry *curentry)
  830. {
  831. grub_err_t err;
  832. if (curentry->comments)
  833. {
  834. err = print (outbuf, curentry->comments,
  835. grub_strlen (curentry->comments));
  836. if (err)
  837. return err;
  838. }
  839. {
  840. struct syslinux_say *say;
  841. for (say = curentry->say; say && say->next; say = say->next);
  842. for (; say && say->prev; say = say->prev)
  843. {
  844. print_string ("echo ");
  845. if (print_escaped (outbuf, say->msg, NULL)) return grub_errno;
  846. print_string ("\n");
  847. }
  848. }
  849. /* FIXME: support help text. */
  850. switch (curentry->entry_type)
  851. {
  852. case KERNEL_LINUX:
  853. {
  854. const char *ptr;
  855. const char *initrd = NULL, *initrde= NULL;
  856. for (ptr = curentry->append; ptr && *ptr; ptr++)
  857. if ((ptr == curentry->append || grub_isspace (ptr[-1]))
  858. && grub_strncasecmp (ptr, "initrd=", sizeof ("initrd=") - 1)
  859. == 0)
  860. break;
  861. if (ptr && *ptr)
  862. {
  863. initrd = ptr + sizeof ("initrd=") - 1;
  864. for (initrde = initrd; *initrde && !grub_isspace (*initrde); initrde++);
  865. }
  866. print_string (" if test x$grub_platform = xpc; then "
  867. "linux_suffix=16; else linux_suffix= ; fi\n");
  868. print_string (" linux$linux_suffix ");
  869. print_file (outbuf, menu, curentry->kernel_file, NULL);
  870. print_string (" ");
  871. if (curentry->append)
  872. {
  873. err = print (outbuf, curentry->append, grub_strlen (curentry->append));
  874. if (err)
  875. return err;
  876. }
  877. print_string ("\n");
  878. if (initrd || curentry->initrds)
  879. {
  880. struct initrd_list *lst;
  881. print_string (" initrd$linux_suffix ");
  882. if (initrd)
  883. {
  884. print_file (outbuf, menu, initrd, initrde);
  885. print_string (" ");
  886. }
  887. for (lst = curentry->initrds; lst; lst = lst->next)
  888. {
  889. print_file (outbuf, menu, lst->file, NULL);
  890. print_string (" ");
  891. }
  892. print_string ("\n");
  893. }
  894. }
  895. break;
  896. case KERNEL_CHAINLOADER:
  897. print_string (" chainloader ");
  898. print_file (outbuf, menu, curentry->kernel_file, NULL);
  899. print_string ("\n");
  900. break;
  901. case KERNEL_CHAINLOADER_BPB:
  902. print_string (" chainloader --bpb ");
  903. print_file (outbuf, menu, curentry->kernel_file, NULL);
  904. print_string ("\n");
  905. break;
  906. case LOCALBOOT:
  907. /* FIXME: support -1. */
  908. /* FIXME: PXELINUX. */
  909. {
  910. int n = grub_strtol (curentry->kernel_file, NULL, 0);
  911. if (n >= 0 && n <= 0x02)
  912. {
  913. print_string (" root=fd");
  914. if (print_num (outbuf, n))
  915. return grub_errno;
  916. print_string (";\n chainloader +1;\n");
  917. break;
  918. }
  919. if (n >= 0x80 && n < 0x8a)
  920. {
  921. print_string (" root=hd");
  922. if (print_num (outbuf, n - 0x80))
  923. return grub_errno;
  924. print_string (";\n chainloader +1;\n");
  925. break;
  926. }
  927. print_string (" # UNSUPPORTED localboot type ");
  928. print_string ("\ntrue;\n");
  929. if (print_num (outbuf, n))
  930. return grub_errno;
  931. print_string ("\n");
  932. break;
  933. }
  934. case KERNEL_COM32:
  935. case KERNEL_COM:
  936. {
  937. char *basename = NULL;
  938. {
  939. char *ptr;
  940. for (ptr = curentry->kernel_file; *ptr; ptr++)
  941. if (*ptr == '/' || *ptr == '\\')
  942. basename = ptr;
  943. }
  944. if (!basename)
  945. basename = curentry->kernel_file;
  946. else
  947. basename++;
  948. if (grub_strcasecmp (basename, "chain.c32") == 0)
  949. {
  950. char *file = NULL;
  951. int is_fd = -1, devn = 0;
  952. int part = -1;
  953. int swap = 0;
  954. char *ptr;
  955. for (ptr = curentry->append; *ptr; )
  956. {
  957. while (grub_isspace (*ptr))
  958. ptr++;
  959. /* FIXME: support mbr: and boot. */
  960. if (ptr[0] == 'h' && ptr[1] == 'd')
  961. {
  962. is_fd = 0;
  963. devn = grub_strtoul (ptr + 2, (const char **)&ptr, 0);
  964. continue;
  965. }
  966. if (grub_strncasecmp (ptr, "file=", 5) == 0)
  967. {
  968. file = ptr + 5;
  969. for (ptr = file; *ptr && !grub_isspace (*ptr); ptr++);
  970. if (*ptr)
  971. {
  972. *ptr = 0;
  973. ptr++;
  974. }
  975. continue;
  976. }
  977. if (grub_strncasecmp (ptr, "swap", sizeof ("swap") - 1) == 0)
  978. {
  979. swap = 1;
  980. ptr += sizeof ("swap") - 1;
  981. continue;
  982. }
  983. if (ptr[0] == 'f' && ptr[1] == 'd')
  984. {
  985. is_fd = 1;
  986. devn = grub_strtoul (ptr + 2, (const char **)&ptr, 0);
  987. continue;
  988. }
  989. if (grub_isdigit (ptr[0]))
  990. {
  991. part = grub_strtoul (ptr, (const char **)&ptr, 0);
  992. continue;
  993. }
  994. /* FIXME: isolinux, ntldr, cmldr, *dos, seg, hide
  995. FIXME: sethidden. */
  996. print_string (" # UNSUPPORTED option ");
  997. if (print (outbuf, ptr, grub_strlen (ptr)))
  998. return 0;
  999. print_string ("\n");
  1000. break;
  1001. }
  1002. if (is_fd == -1)
  1003. {
  1004. print_string (" # no drive specified\n");
  1005. break;
  1006. }
  1007. if (!*ptr)
  1008. {
  1009. print_string (is_fd ? " root=fd": " root=hd");
  1010. if (print_num (outbuf, devn))
  1011. return grub_errno;
  1012. if (part != -1)
  1013. {
  1014. print_string (",");
  1015. if (print_num (outbuf, part + 1))
  1016. return grub_errno;
  1017. }
  1018. print_string (";\n");
  1019. if (file)
  1020. {
  1021. print_string (" chainloader ");
  1022. print_file (outbuf, menu, file, NULL);
  1023. print_string (";\n");
  1024. }
  1025. else
  1026. print_string (" chainloader +1;\n");
  1027. if (swap)
  1028. print_string (" drivemap -s hd0 \"root\";\n");
  1029. }
  1030. break;
  1031. }
  1032. if (grub_strcasecmp (basename, "mboot.c32") == 0)
  1033. {
  1034. char *ptr;
  1035. int first = 1;
  1036. int is_kernel = 1;
  1037. for (ptr = curentry->append; *ptr; )
  1038. {
  1039. char *ptrr = ptr;
  1040. while (*ptr && !grub_isspace (*ptr))
  1041. ptr++;
  1042. if (ptrr + 2 == ptr && ptrr[0] == '-' && ptrr[1] == '-')
  1043. {
  1044. print_string ("\n");
  1045. first = 1;
  1046. continue;
  1047. }
  1048. if (first)
  1049. {
  1050. if (is_kernel)
  1051. print_string (" multiboot ");
  1052. else
  1053. print_string (" module ");
  1054. first = 0;
  1055. is_kernel = 0;
  1056. if (print_file (outbuf, menu, ptrr, ptr))
  1057. return grub_errno;
  1058. continue;
  1059. }
  1060. if (print_escaped (outbuf, ptrr, ptr))
  1061. return grub_errno;
  1062. }
  1063. break;
  1064. }
  1065. if (grub_strcasecmp (basename, "ifcpu64.c32") == 0)
  1066. {
  1067. char *lm, *lme, *pae = 0, *paee = 0, *i386s = 0, *i386e = 0;
  1068. char *ptr;
  1069. ptr = curentry->append;
  1070. while (grub_isspace (*ptr))
  1071. ptr++;
  1072. lm = ptr;
  1073. while (*ptr && !grub_isspace (*ptr))
  1074. ptr++;
  1075. lme = ptr;
  1076. while (grub_isspace (*ptr))
  1077. ptr++;
  1078. if (ptr[0] == '-' && ptr[1] == '-')
  1079. {
  1080. ptr += 2;
  1081. while (grub_isspace (*ptr))
  1082. ptr++;
  1083. pae = ptr;
  1084. while (*ptr && !grub_isspace (*ptr))
  1085. ptr++;
  1086. paee = ptr;
  1087. }
  1088. while (grub_isspace (*ptr))
  1089. ptr++;
  1090. if (ptr[0] == '-' && ptr[1] == '-')
  1091. {
  1092. ptr += 2;
  1093. while (grub_isspace (*ptr))
  1094. ptr++;
  1095. i386s = ptr;
  1096. while (*ptr && !grub_isspace (*ptr))
  1097. ptr++;
  1098. i386e = ptr;
  1099. }
  1100. *lme = '\0';
  1101. if (paee)
  1102. *paee = '\0';
  1103. if (i386e)
  1104. *i386e = '\0';
  1105. if (!i386s)
  1106. {
  1107. i386s = pae;
  1108. pae = 0;
  1109. }
  1110. print_string ("if cpuid --long-mode; then true;\n");
  1111. if (print_entry (outbuf, menu, lm))
  1112. return grub_errno;
  1113. if (pae)
  1114. {
  1115. print_string ("elif cpuid --pae; then true;\n");
  1116. if (print_entry (outbuf, menu, pae))
  1117. return grub_errno;
  1118. }
  1119. print_string ("else\n");
  1120. if (print_entry (outbuf, menu, i386s))
  1121. return grub_errno;
  1122. print_string ("fi\n");
  1123. break;
  1124. }
  1125. if (grub_strcasecmp (basename, "reboot.c32") == 0)
  1126. {
  1127. print_string (" reboot\n");
  1128. break;
  1129. }
  1130. if (grub_strcasecmp (basename, "poweroff.com") == 0)
  1131. {
  1132. print_string (" halt\n");
  1133. break;
  1134. }
  1135. if (grub_strcasecmp (basename, "whichsys.c32") == 0)
  1136. {
  1137. grub_syslinux_flavour_t flavour = GRUB_SYSLINUX_ISOLINUX;
  1138. const char *flav[] =
  1139. {
  1140. [GRUB_SYSLINUX_ISOLINUX] = "iso",
  1141. [GRUB_SYSLINUX_PXELINUX] = "pxe",
  1142. [GRUB_SYSLINUX_SYSLINUX] = "sys"
  1143. };
  1144. char *ptr;
  1145. for (ptr = curentry->append; *ptr; )
  1146. {
  1147. char *bptr, c;
  1148. while (grub_isspace (*ptr))
  1149. ptr++;
  1150. if (grub_strncasecmp (ptr, "-iso-", 5) == 0)
  1151. {
  1152. ptr += sizeof ("-iso-") - 1;
  1153. flavour = GRUB_SYSLINUX_ISOLINUX;
  1154. continue;
  1155. }
  1156. if (grub_strncasecmp (ptr, "-pxe-", 5) == 0)
  1157. {
  1158. ptr += sizeof ("-pxe-") - 1;
  1159. flavour = GRUB_SYSLINUX_PXELINUX;
  1160. continue;
  1161. }
  1162. if (grub_strncasecmp (ptr, "-sys-", 5) == 0)
  1163. {
  1164. ptr += sizeof ("-sys-") - 1;
  1165. flavour = GRUB_SYSLINUX_SYSLINUX;
  1166. continue;
  1167. }
  1168. bptr = ptr;
  1169. while (*ptr && !grub_isspace (*ptr))
  1170. ptr++;
  1171. c = *ptr;
  1172. *ptr = '\0';
  1173. if (menu->flavour == GRUB_SYSLINUX_UNKNOWN
  1174. && flavour == GRUB_SYSLINUX_ISOLINUX)
  1175. {
  1176. print_string ("if [ x$syslinux_flavour = xiso -o x$syslinux_flavour = x ]; then true;\n");
  1177. menu->flavour = GRUB_SYSLINUX_ISOLINUX;
  1178. print_entry (outbuf, menu, bptr);
  1179. menu->flavour = GRUB_SYSLINUX_UNKNOWN;
  1180. print_string ("fi\n");
  1181. }
  1182. else if (menu->flavour == GRUB_SYSLINUX_UNKNOWN)
  1183. {
  1184. print_string ("if [ x$syslinux_flavour = x");
  1185. err = print (outbuf, flav[flavour], grub_strlen (flav[flavour]));
  1186. if (err)
  1187. return err;
  1188. print_string (" ]; then true;\n");
  1189. menu->flavour = flavour;
  1190. print_entry (outbuf, menu, bptr);
  1191. menu->flavour = GRUB_SYSLINUX_UNKNOWN;
  1192. print_string ("fi\n");
  1193. }
  1194. if (menu->flavour != GRUB_SYSLINUX_UNKNOWN
  1195. && menu->flavour == flavour)
  1196. print_entry (outbuf, menu, bptr);
  1197. *ptr = c;
  1198. }
  1199. break;
  1200. }
  1201. if (grub_strcasecmp (basename, "menu.c32") == 0 ||
  1202. grub_strcasecmp (basename, "vesamenu.c32") == 0)
  1203. {
  1204. char *ptr;
  1205. char *end;
  1206. ptr = curentry->append;
  1207. if (!ptr)
  1208. return grub_errno;
  1209. while (*ptr)
  1210. {
  1211. end = ptr;
  1212. for (end = ptr; *end && !grub_isspace (*end); end++);
  1213. if (*end)
  1214. *end++ = '\0';
  1215. /* "~" is supposed to be current file, so let's skip it */
  1216. if (grub_strcmp (ptr, "~") != 0)
  1217. {
  1218. err = print_config (outbuf, menu, ptr, "");
  1219. if (err != GRUB_ERR_NONE)
  1220. break;
  1221. }
  1222. for (ptr = end; *ptr && grub_isspace (*ptr); ptr++);
  1223. }
  1224. err = GRUB_ERR_NONE;
  1225. break;
  1226. }
  1227. /* FIXME: gdb, GFXBoot, Hdt, Ifcpu, Ifplop, Kbdmap,
  1228. FIXME: Linux, Lua, Meminfo, rosh, Sanbboot */
  1229. print_string (" # UNSUPPORTED com(32) ");
  1230. err = print (outbuf, basename, grub_strlen (basename));
  1231. if (err)
  1232. return err;
  1233. print_string ("\ntrue;\n");
  1234. break;
  1235. }
  1236. case KERNEL_CONFIG:
  1237. {
  1238. const char *ap;
  1239. ap = curentry->append;
  1240. if (!ap)
  1241. ap = curentry->argument;
  1242. if (!ap)
  1243. ap = "";
  1244. print_config (outbuf, menu, curentry->kernel_file, ap);
  1245. }
  1246. break;
  1247. case KERNEL_NO_KERNEL:
  1248. /* FIXME: support this. */
  1249. case KERNEL_BIN:
  1250. case KERNEL_PXE:
  1251. case KERNEL_IMG:
  1252. print_string (" # UNSUPPORTED entry type ");
  1253. if (print_num (outbuf, curentry->entry_type))
  1254. return grub_errno;
  1255. print_string ("\ntrue;\n");
  1256. break;
  1257. }
  1258. return GRUB_ERR_NONE;
  1259. }
  1260. static grub_err_t
  1261. print_entry (struct output_buffer *outbuf,
  1262. struct syslinux_menu *menu,
  1263. const char *str)
  1264. {
  1265. struct syslinux_menuentry *curentry;
  1266. for (curentry = menu->entries; curentry; curentry = curentry->next)
  1267. if (grub_strcasecmp (curentry->label, str) == 0)
  1268. {
  1269. grub_err_t err;
  1270. err = write_entry (outbuf, menu, curentry);
  1271. if (err)
  1272. return err;
  1273. }
  1274. return GRUB_ERR_NONE;
  1275. }
  1276. static void
  1277. free_menu (struct syslinux_menu *menu)
  1278. {
  1279. struct syslinux_say *say, *nsay;
  1280. struct syslinux_menuentry *entry, *nentry;
  1281. grub_free (menu->def);
  1282. grub_free (menu->comments);
  1283. grub_free (menu->background);
  1284. for (say = menu->say; say ; say = nsay)
  1285. {
  1286. nsay = say->next;
  1287. grub_free (say);
  1288. }
  1289. for (entry = menu->entries; entry ; entry = nentry)
  1290. {
  1291. nentry = entry->next;
  1292. struct initrd_list *initrd, *ninitrd;
  1293. for (initrd = entry->initrds; initrd ; initrd = ninitrd)
  1294. {
  1295. ninitrd = initrd->next;
  1296. grub_free (initrd->file);
  1297. grub_free (initrd);
  1298. }
  1299. grub_free (entry->comments);
  1300. grub_free (entry->kernel_file);
  1301. grub_free (entry->label);
  1302. grub_free (entry->extlabel);
  1303. grub_free (entry->append);
  1304. grub_free (entry->help);
  1305. grub_free (entry);
  1306. }
  1307. }
  1308. static grub_err_t
  1309. config_file (struct output_buffer *outbuf,
  1310. const char *root, const char *target_root,
  1311. const char *cwd, const char *target_cwd,
  1312. const char *fname, struct syslinux_menu *parent,
  1313. grub_syslinux_flavour_t flav)
  1314. {
  1315. grub_err_t err;
  1316. struct syslinux_menu menu;
  1317. struct syslinux_menuentry *curentry, *lentry;
  1318. struct syslinux_say *say;
  1319. grub_memset (&menu, 0, sizeof (menu));
  1320. menu.flavour = flav;
  1321. menu.root_read_directory = root;
  1322. menu.root_target_directory = target_root;
  1323. menu.current_read_directory = cwd;
  1324. menu.current_target_directory = target_cwd;
  1325. menu.filename = fname;
  1326. menu.parent = parent;
  1327. err = syslinux_parse_real (&menu);
  1328. if (err)
  1329. return err;
  1330. for (say = menu.say; say && say->next; say = say->next);
  1331. for (; say && say->prev; say = say->prev)
  1332. {
  1333. print_string ("echo ");
  1334. err = print_escaped (outbuf, say->msg, NULL);
  1335. if (err)
  1336. return err;
  1337. print_string ("\n");
  1338. }
  1339. if (menu.background)
  1340. {
  1341. print_string (" background_image ");
  1342. err = print_file (outbuf, &menu, menu.background, NULL);
  1343. if (err)
  1344. return err;
  1345. print_string ("\n");
  1346. }
  1347. if (menu.comments)
  1348. {
  1349. err = print (outbuf, menu.comments, grub_strlen (menu.comments));
  1350. if (err)
  1351. return err;
  1352. }
  1353. if (menu.timeout == 0 && menu.entries && menu.def)
  1354. {
  1355. err = print_entry (outbuf, &menu, menu.def);
  1356. if (err)
  1357. return err;
  1358. }
  1359. else if (menu.entries)
  1360. {
  1361. for (curentry = menu.entries; curentry->next; curentry = curentry->next);
  1362. lentry = curentry;
  1363. print_string ("set timeout=");
  1364. err = print_num (outbuf, (menu.timeout + 9) / 10);
  1365. if (err)
  1366. return err;
  1367. print_string ("\n");
  1368. if (menu.def)
  1369. {
  1370. print_string (" default=");
  1371. err = print_escaped (outbuf, menu.def, NULL);
  1372. if (err)
  1373. return err;
  1374. print_string ("\n");
  1375. }
  1376. for (curentry = lentry; curentry; curentry = curentry->prev)
  1377. {
  1378. print_string ("menuentry ");
  1379. err = print_escaped (outbuf,
  1380. curentry->extlabel ? : curentry->label, NULL);
  1381. if (err)
  1382. return err;
  1383. if (curentry->hotkey)
  1384. {
  1385. char hk[] = { curentry->hotkey, '\0' };
  1386. print_string (" --hotkey '");
  1387. print_string (hk);
  1388. print_string ("'");
  1389. }
  1390. print_string (" --id ");
  1391. err = print_escaped (outbuf, curentry->label, NULL);
  1392. if (err)
  1393. return err;
  1394. print_string (" {\n");
  1395. err = write_entry (outbuf, &menu, curentry);
  1396. if (err)
  1397. return err;
  1398. print_string ("}\n");
  1399. }
  1400. }
  1401. free_menu (&menu);
  1402. return GRUB_ERR_NONE;
  1403. }
  1404. char *
  1405. grub_syslinux_config_file (const char *base, const char *target_base,
  1406. const char *cwd, const char *target_cwd,
  1407. const char *fname, grub_syslinux_flavour_t flav)
  1408. {
  1409. struct output_buffer outbuf = { 0, 0, 0 };
  1410. grub_err_t err;
  1411. err = config_file (&outbuf, base, target_base, cwd, target_cwd,
  1412. fname, NULL, flav);
  1413. if (err)
  1414. return NULL;
  1415. err = print (&outbuf, "\0", 1);
  1416. if (err)
  1417. return NULL;
  1418. return outbuf.buf;
  1419. }