Advertisement
Guest User

grub 2 module for appending extra args

a guest
Jul 28th, 2020
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 34.48 KB | None | 0 0
  1. /* append.c - append extra command line args to linux kernel */
  2. /*
  3.  *  GRUB  --  GRand Unified Bootloader
  4.  *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
  5.  *  Copyright (C) 2003  NIIBE Yutaka <gniibe@m17n.org>
  6.  *
  7.  *  GRUB is free software: you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation, either version 3 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  GRUB is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  19.  */
  20.  
  21. #include <grub/extcmd.h>
  22.  
  23. #include <grub/loader.h>
  24. #include <grub/memory.h>
  25. #include <grub/normal.h>
  26. #include <grub/file.h>
  27. #include <grub/disk.h>
  28. #include <grub/err.h>
  29. #include <grub/misc.h>
  30. #include <grub/types.h>
  31. #include <grub/dl.h>
  32. #include <grub/mm.h>
  33. #include <grub/term.h>
  34. #include <grub/cpu/linux.h>
  35. #include <grub/video.h>
  36. #include <grub/video_fb.h>
  37. #include <grub/command.h>
  38. #include <grub/i386/relocator.h>
  39. #include <grub/i18n.h>
  40. #include <grub/lib/cmdline.h>
  41. #include <grub/linux.h>
  42.  
  43. GRUB_MOD_LICENSE ("GPLv3+");
  44.  
  45. #ifdef GRUB_MACHINE_PCBIOS
  46. #include <grub/i386/pc/vesa_modes_table.h>
  47. #endif
  48.  
  49. #ifdef GRUB_MACHINE_EFI
  50. #include <grub/efi/efi.h>
  51. #define HAS_VGA_TEXT 0
  52. #define DEFAULT_VIDEO_MODE "auto"
  53. #define ACCEPTS_PURE_TEXT 0
  54. #elif defined (GRUB_MACHINE_IEEE1275)
  55. #include <grub/ieee1275/ieee1275.h>
  56. #define HAS_VGA_TEXT 0
  57. #define DEFAULT_VIDEO_MODE "text"
  58. #define ACCEPTS_PURE_TEXT 1
  59. #else
  60. #include <grub/i386/pc/vbe.h>
  61. #include <grub/i386/pc/console.h>
  62. #define HAS_VGA_TEXT 1
  63. #define DEFAULT_VIDEO_MODE "text"
  64. #define ACCEPTS_PURE_TEXT 1
  65. #endif
  66.  
  67. static grub_dl_t my_mod;
  68.  
  69. static grub_size_t linux_mem_size;
  70. static int loaded;
  71. static void *prot_mode_mem;
  72. static grub_addr_t prot_mode_target;
  73. static void *initrd_mem;
  74. static grub_addr_t initrd_mem_target;
  75. static grub_size_t prot_init_space;
  76. static struct grub_relocator *relocator = NULL;
  77. static void *efi_mmap_buf;
  78. static grub_size_t maximal_cmdline_size;
  79. static struct linux_kernel_params linux_params;
  80. static char *linux_cmdline;
  81. #ifdef GRUB_MACHINE_EFI
  82. static grub_efi_uintn_t efi_mmap_size;
  83. #else
  84. static const grub_size_t efi_mmap_size = 0;
  85. #endif
  86.  
  87. // To remember what we should append
  88. static int appended_args_count = 0;
  89. static char **appended_args = NULL;
  90.  
  91. // Clean all remembered args
  92. static void clean_args(void)
  93. {
  94.   int i;
  95.   if(appended_args_count == 0)
  96.     return;
  97.   if(!appended_args)
  98.   {
  99.     appended_args_count = 0;
  100.     return;
  101.   }
  102.  
  103.   for(i = 0; i < appended_args_count; ++i)
  104.     grub_free(appended_args[i]);
  105.   grub_free(appended_args);
  106.   appended_args_count = 0;
  107. }
  108.  
  109. static grub_err_t grub_cmd_append(grub_extcmd_context_t ctxt __attribute__((unused)),
  110.     int argc, char **args)
  111. {
  112.   int i;
  113.  
  114.   if(argc < 1) // Print what we have now!
  115.   {
  116.     if(appended_args_count == 0 || !appended_args)
  117.       grub_printf("%s\n", "No arguments to append to kernel command line...");
  118.     else
  119.     {
  120.       grub_printf("%s:\n", "Arguments to append to kernel command line");
  121.       for(i = 0; i < appended_args_count; ++i)
  122.         grub_printf(" %s\n", appended_args[i] );
  123.     }
  124.   }
  125.   else // Set new arguments to append
  126.   {
  127.     clean_args(); // Clean old args
  128.     appended_args = grub_malloc(argc * sizeof(char*) );
  129.     if(!appended_args) // No Mem??
  130.     {
  131.       grub_printf("%s\n", "No memeory to copy args??");
  132.       return 0;
  133.     }
  134.     for(i = 0; i < argc; ++i)
  135.     {
  136.       appended_args[i] = grub_strdup(args[i] );
  137.       if(!appended_args[i] )
  138.       {
  139.         grub_printf("%s (%d)\n", "No memeory to copy all args", i);
  140.         break;
  141.       }
  142.     }
  143.     appended_args_count = i; // Can be less than argc if no mem(
  144.   }
  145.  
  146. // After that we can write something like this:
  147. //    grub_create_loader_cmdline (appended_args_count, appended_args, cmdline + offset, size - offset);
  148. // but how to find offset???
  149.  
  150.   return 0;
  151. }
  152.  
  153.  
  154. /// FROM loader/i386/linux.c
  155. static inline grub_size_t
  156. page_align (grub_size_t size)
  157. {
  158.   return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
  159. }
  160.  
  161. #ifdef GRUB_MACHINE_EFI
  162. /* Find the optimal number of pages for the memory map. Is it better to
  163.    move this code to efi/mm.c?  */
  164. static grub_efi_uintn_t
  165. find_efi_mmap_size (void)
  166. {
  167.   static grub_efi_uintn_t mmap_size = 0;
  168.  
  169.   if (mmap_size != 0)
  170.     return mmap_size;
  171.  
  172.   mmap_size = (1 << 12);
  173.   while (1)
  174.     {
  175.       int ret;
  176.       grub_efi_memory_descriptor_t *mmap;
  177.       grub_efi_uintn_t desc_size;
  178.       grub_efi_uintn_t cur_mmap_size = mmap_size;
  179.  
  180.       mmap = grub_malloc (cur_mmap_size);
  181.       if (! mmap)
  182.     return 0;
  183.  
  184.       ret = grub_efi_get_memory_map (&cur_mmap_size, mmap, 0, &desc_size, 0);
  185.       grub_free (mmap);
  186.  
  187.       if (ret < 0)
  188.     {
  189.       grub_error (GRUB_ERR_IO, "cannot get memory map");
  190.       return 0;
  191.     }
  192.       else if (ret > 0)
  193.     break;
  194.  
  195.       if (mmap_size < cur_mmap_size)
  196.     mmap_size = cur_mmap_size;
  197.       mmap_size += (1 << 12);
  198.     }
  199.  
  200.   /* Increase the size a bit for safety, because GRUB allocates more on
  201.      later, and EFI itself may allocate more.  */
  202.   mmap_size += (3 << 12);
  203.  
  204.   mmap_size = page_align (mmap_size);
  205.   return mmap_size;
  206. }
  207.  
  208. #endif
  209.  
  210. /* Helper for find_mmap_size.  */
  211. static int
  212. count_hook (grub_uint64_t addr __attribute__ ((unused)),
  213.         grub_uint64_t size __attribute__ ((unused)),
  214.         grub_memory_type_t type __attribute__ ((unused)), void *data)
  215. {
  216.   grub_size_t *count = data;
  217.  
  218.   (*count)++;
  219.   return 0;
  220. }
  221.  
  222. /* Find the optimal number of pages for the memory map. */
  223. static grub_size_t
  224. find_mmap_size (void)
  225. {
  226.   grub_size_t count = 0, mmap_size;
  227.  
  228.   grub_mmap_iterate (count_hook, &count);
  229.  
  230.   mmap_size = count * sizeof (struct grub_e820_mmap);
  231.  
  232.   /* Increase the size a bit for safety, because GRUB allocates more on
  233.      later.  */
  234.   mmap_size += (1 << 12);
  235.  
  236.   return page_align (mmap_size);
  237. }
  238.  
  239. static void
  240. free_pages (void)
  241. {
  242.   grub_relocator_unload (relocator);
  243.   relocator = NULL;
  244.   prot_mode_mem = initrd_mem = 0;
  245.   prot_mode_target = initrd_mem_target = 0;
  246. }
  247.  
  248. /* Allocate pages for the real mode code and the protected mode code
  249.    for linux as well as a memory map buffer.  */
  250. static grub_err_t
  251. allocate_pages (grub_size_t prot_size, grub_size_t *align,
  252.         grub_size_t min_align, int relocatable,
  253.         grub_uint64_t preferred_address)
  254. {
  255.   grub_err_t err;
  256.  
  257.   if (prot_size == 0)
  258.     prot_size = 1;
  259.  
  260.   prot_size = page_align (prot_size);
  261.  
  262.   /* Initialize the memory pointers with NULL for convenience.  */
  263.   free_pages ();
  264.  
  265.   relocator = grub_relocator_new ();
  266.   if (!relocator)
  267.     {
  268.       err = grub_errno;
  269.       goto fail;
  270.     }
  271.  
  272.   /* FIXME: Should request low memory from the heap when this feature is
  273.      implemented.  */
  274.  
  275.   {
  276.     grub_relocator_chunk_t ch;
  277.     if (relocatable)
  278.       {
  279.     err = grub_relocator_alloc_chunk_align (relocator, &ch,
  280.                         preferred_address,
  281.                         preferred_address,
  282.                         prot_size, 1,
  283.                         GRUB_RELOCATOR_PREFERENCE_LOW,
  284.                         1);
  285.     for (; err && *align + 1 > min_align; (*align)--)
  286.       {
  287.         grub_errno = GRUB_ERR_NONE;
  288.         err = grub_relocator_alloc_chunk_align (relocator, &ch,
  289.                             0x1000000,
  290.                             0xffffffff & ~prot_size,
  291.                             prot_size, 1 << *align,
  292.                             GRUB_RELOCATOR_PREFERENCE_LOW,
  293.                             1);
  294.       }
  295.     if (err)
  296.       goto fail;
  297.       }
  298.     else
  299.       err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  300.                          preferred_address,
  301.                          prot_size);
  302.     if (err)
  303.       goto fail;
  304.     prot_mode_mem = get_virtual_current_address (ch);
  305.     prot_mode_target = get_physical_target_address (ch);
  306.   }
  307.  
  308.   grub_dprintf ("linux", "prot_mode_mem = %p, prot_mode_target = %lx, prot_size = %x\n",
  309.                 prot_mode_mem, (unsigned long) prot_mode_target,
  310.         (unsigned) prot_size);
  311.   return GRUB_ERR_NONE;
  312.  
  313.  fail:
  314.   free_pages ();
  315.   return err;
  316. }
  317.  
  318. static grub_err_t
  319. grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
  320.                       grub_uint64_t start, grub_uint64_t size,
  321.                       grub_uint32_t type)
  322. {
  323.   int n = *e820_num;
  324.  
  325.   if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
  326.       (e820_map[n - 1].type == type))
  327.       e820_map[n - 1].size += size;
  328.   else
  329.     {
  330.       e820_map[n].addr = start;
  331.       e820_map[n].size = size;
  332.       e820_map[n].type = type;
  333.       (*e820_num)++;
  334.     }
  335.   return GRUB_ERR_NONE;
  336. }
  337.  
  338. static grub_err_t
  339. grub_linux_setup_video (struct linux_kernel_params *params)
  340. {
  341.   struct grub_video_mode_info mode_info;
  342.   void *framebuffer;
  343.   grub_err_t err;
  344.   grub_video_driver_id_t driver_id;
  345.   const char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb");
  346.  
  347.   driver_id = grub_video_get_driver_id ();
  348.  
  349.   if (driver_id == GRUB_VIDEO_DRIVER_NONE)
  350.     return 1;
  351.  
  352.   err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
  353.  
  354.   if (err)
  355.     {
  356.       grub_errno = GRUB_ERR_NONE;
  357.       return 1;
  358.     }
  359.  
  360.   params->lfb_width = mode_info.width;
  361.   params->lfb_height = mode_info.height;
  362.   params->lfb_depth = mode_info.bpp;
  363.   params->lfb_line_len = mode_info.pitch;
  364.  
  365.   params->lfb_base = (grub_size_t) framebuffer;
  366.   params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536);
  367.  
  368.   params->red_mask_size = mode_info.red_mask_size;
  369.   params->red_field_pos = mode_info.red_field_pos;
  370.   params->green_mask_size = mode_info.green_mask_size;
  371.   params->green_field_pos = mode_info.green_field_pos;
  372.   params->blue_mask_size = mode_info.blue_mask_size;
  373.   params->blue_field_pos = mode_info.blue_field_pos;
  374.   params->reserved_mask_size = mode_info.reserved_mask_size;
  375.   params->reserved_field_pos = mode_info.reserved_field_pos;
  376.  
  377.   if (gfxlfbvar && (gfxlfbvar[0] == '1' || gfxlfbvar[0] == 'y'))
  378.     params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
  379.   else
  380.     {
  381.       switch (driver_id)
  382.     {
  383.     case GRUB_VIDEO_DRIVER_VBE:
  384.       params->lfb_size >>= 16;
  385.       params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
  386.       break;
  387.    
  388.     case GRUB_VIDEO_DRIVER_EFI_UGA:
  389.     case GRUB_VIDEO_DRIVER_EFI_GOP:
  390.       params->have_vga = GRUB_VIDEO_LINUX_TYPE_EFIFB;
  391.       break;
  392.  
  393.       /* FIXME: check if better id is available.  */
  394.     case GRUB_VIDEO_DRIVER_SM712:
  395.     case GRUB_VIDEO_DRIVER_SIS315PRO:
  396.     case GRUB_VIDEO_DRIVER_VGA:
  397.     case GRUB_VIDEO_DRIVER_CIRRUS:
  398.     case GRUB_VIDEO_DRIVER_BOCHS:
  399.     case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E:
  400.     case GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A:
  401.     case GRUB_VIDEO_DRIVER_IEEE1275:
  402.     case GRUB_VIDEO_DRIVER_COREBOOT:
  403.       /* Make gcc happy. */
  404.     case GRUB_VIDEO_DRIVER_XEN:
  405.     case GRUB_VIDEO_DRIVER_SDL:
  406.     case GRUB_VIDEO_DRIVER_NONE:
  407.     case GRUB_VIDEO_ADAPTER_CAPTURE:
  408.       params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
  409.       break;
  410.     }
  411.     }
  412.  
  413. #ifdef GRUB_MACHINE_PCBIOS
  414.   /* VESA packed modes may come with zeroed mask sizes, which need
  415.      to be set here according to DAC Palette width.  If we don't,
  416.      this results in Linux displaying a black screen.  */
  417.   if (driver_id == GRUB_VIDEO_DRIVER_VBE && mode_info.bpp <= 8)
  418.     {
  419.       struct grub_vbe_info_block controller_info;
  420.       int status;
  421.       int width = 8;
  422.  
  423.       status = grub_vbe_bios_get_controller_info (&controller_info);
  424.  
  425.       if (status == GRUB_VBE_STATUS_OK &&
  426.       (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH))
  427.     status = grub_vbe_bios_set_dac_palette_width (&width);
  428.  
  429.       if (status != GRUB_VBE_STATUS_OK)
  430.     /* 6 is default after mode reset.  */
  431.     width = 6;
  432.  
  433.       params->red_mask_size = params->green_mask_size
  434.     = params->blue_mask_size = width;
  435.       params->reserved_mask_size = 0;
  436.     }
  437. #endif
  438.  
  439.   return GRUB_ERR_NONE;
  440. }
  441.  
  442. /* Context for grub_linux_boot.  */
  443. struct grub_linux_boot_ctx
  444. {
  445.   grub_addr_t real_mode_target;
  446.   grub_size_t real_size;
  447.   struct linux_kernel_params *params;
  448.   int e820_num;
  449. };
  450.  
  451. /* Helper for grub_linux_boot.  */
  452. static int
  453. grub_linux_boot_mmap_find (grub_uint64_t addr, grub_uint64_t size,
  454.                grub_memory_type_t type, void *data)
  455. {
  456.   struct grub_linux_boot_ctx *ctx = data;
  457.  
  458.   /* We must put real mode code in the traditional space.  */
  459.   if (type != GRUB_MEMORY_AVAILABLE || addr > 0x90000)
  460.     return 0;
  461.  
  462.   if (addr + size < 0x10000)
  463.     return 0;
  464.  
  465.   if (addr < 0x10000)
  466.     {
  467.       size += addr - 0x10000;
  468.       addr = 0x10000;
  469.     }
  470.  
  471.   if (addr + size > 0x90000)
  472.     size = 0x90000 - addr;
  473.  
  474.   if (ctx->real_size + efi_mmap_size > size)
  475.     return 0;
  476.  
  477.   grub_dprintf ("linux", "addr = %lx, size = %x, need_size = %x\n",
  478.         (unsigned long) addr,
  479.         (unsigned) size,
  480.         (unsigned) (ctx->real_size + efi_mmap_size));
  481.   ctx->real_mode_target = ((addr + size) - (ctx->real_size + efi_mmap_size));
  482.   return 1;
  483. }
  484.  
  485. /* GRUB types conveniently match E820 types.  */
  486. static int
  487. grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_uint64_t size,
  488.                grub_memory_type_t type, void *data)
  489. {
  490.   struct grub_linux_boot_ctx *ctx = data;
  491.  
  492.   if (grub_e820_add_region (ctx->params->e820_map, &ctx->e820_num,
  493.                 addr, size, type))
  494.     return 1;
  495.  
  496.   return 0;
  497. }
  498.  
  499. static grub_err_t
  500. grub_linux_boot (void)
  501. {
  502.   grub_err_t err = 0;
  503.   const char *modevar;
  504.   char *tmp;
  505.   struct grub_relocator32_state state;
  506.   void *real_mode_mem;
  507.   struct grub_linux_boot_ctx ctx = {
  508.     .real_mode_target = 0
  509.   };
  510.   grub_size_t mmap_size;
  511.   grub_size_t cl_offset;
  512.  
  513. #ifdef GRUB_MACHINE_IEEE1275
  514.   {
  515.     const char *bootpath;
  516.     grub_ssize_t len;
  517.  
  518.     bootpath = grub_env_get ("root");
  519.     if (bootpath)
  520.       grub_ieee1275_set_property (grub_ieee1275_chosen,
  521.                   "bootpath", bootpath,
  522.                   grub_strlen (bootpath) + 1,
  523.                   &len);
  524.     linux_params.ofw_signature = GRUB_LINUX_OFW_SIGNATURE;
  525.     linux_params.ofw_num_items = 1;
  526.     linux_params.ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn;
  527.     linux_params.ofw_idt = 0;
  528.   }
  529. #endif
  530.  
  531.   modevar = grub_env_get ("gfxpayload");
  532.  
  533.   /* Now all graphical modes are acceptable.
  534.      May change in future if we have modes without framebuffer.  */
  535.   if (modevar && *modevar != 0)
  536.     {
  537.       tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
  538.       if (! tmp)
  539.     return grub_errno;
  540. #if ACCEPTS_PURE_TEXT
  541.       err = grub_video_set_mode (tmp, 0, 0);
  542. #else
  543.       err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
  544. #endif
  545.       grub_free (tmp);
  546.     }
  547.   else       /* We can't go back to text mode from coreboot fb.  */
  548. #ifdef GRUB_MACHINE_COREBOOT
  549.     if (grub_video_get_driver_id () == GRUB_VIDEO_DRIVER_COREBOOT)
  550.       err = GRUB_ERR_NONE;
  551.     else
  552. #endif
  553.       {
  554. #if ACCEPTS_PURE_TEXT
  555.     err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
  556. #else
  557.     err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
  558.                  GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
  559. #endif
  560.       }
  561.  
  562.   if (err)
  563.     {
  564.       grub_print_error ();
  565.       grub_puts_ (N_("Booting in blind mode"));
  566.       grub_errno = GRUB_ERR_NONE;
  567.     }
  568.  
  569.   if (grub_linux_setup_video (&linux_params))
  570.     {
  571. #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
  572.       linux_params.have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT;
  573.       linux_params.video_mode = 0x3;
  574. #else
  575.       linux_params.have_vga = 0;
  576.       linux_params.video_mode = 0;
  577.       linux_params.video_width = 0;
  578.       linux_params.video_height = 0;
  579. #endif
  580.     }
  581.  
  582.  
  583. #ifndef GRUB_MACHINE_IEEE1275
  584.   if (linux_params.have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT)
  585. #endif
  586.     {
  587.       grub_term_output_t term;
  588.       int found = 0;
  589.       FOR_ACTIVE_TERM_OUTPUTS(term)
  590.     if (grub_strcmp (term->name, "vga_text") == 0
  591.         || grub_strcmp (term->name, "console") == 0
  592.         || grub_strcmp (term->name, "ofconsole") == 0)
  593.       {
  594.         struct grub_term_coordinate pos = grub_term_getxy (term);
  595.         linux_params.video_cursor_x = pos.x;
  596.         linux_params.video_cursor_y = pos.y;
  597.         linux_params.video_width = grub_term_width (term);
  598.         linux_params.video_height = grub_term_height (term);
  599.         found = 1;
  600.         break;
  601.       }
  602.       if (!found)
  603.     {
  604.       linux_params.video_cursor_x = 0;
  605.       linux_params.video_cursor_y = 0;
  606.       linux_params.video_width = 80;
  607.       linux_params.video_height = 25;
  608.     }
  609.     }
  610.  
  611.   mmap_size = find_mmap_size ();
  612.   /* Make sure that each size is aligned to a page boundary.  */
  613.   cl_offset = ALIGN_UP (mmap_size + sizeof (linux_params), 4096);
  614.   if (cl_offset < ((grub_size_t) linux_params.setup_sects << GRUB_DISK_SECTOR_BITS))
  615.     cl_offset = ALIGN_UP ((grub_size_t) (linux_params.setup_sects
  616.                      << GRUB_DISK_SECTOR_BITS), 4096);
  617.   ctx.real_size = ALIGN_UP (cl_offset + maximal_cmdline_size, 4096);
  618.  
  619. #ifdef GRUB_MACHINE_EFI
  620.   efi_mmap_size = find_efi_mmap_size ();
  621.   if (efi_mmap_size == 0)
  622.     return grub_errno;
  623. #endif
  624.  
  625.   grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n",
  626.         (unsigned) ctx.real_size, (unsigned) mmap_size);
  627.  
  628. #ifdef GRUB_MACHINE_EFI
  629.   grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 1);
  630.   if (! ctx.real_mode_target)
  631.     grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 0);
  632. #else
  633.   grub_mmap_iterate (grub_linux_boot_mmap_find, &ctx);
  634. #endif
  635.   grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n",
  636.                 (unsigned long) ctx.real_mode_target,
  637.         (unsigned) ctx.real_size,
  638.         (unsigned) efi_mmap_size);
  639.  
  640.   if (! ctx.real_mode_target)
  641.     return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
  642.  
  643.   {
  644.     grub_relocator_chunk_t ch;
  645.     err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  646.                        ctx.real_mode_target,
  647.                        (ctx.real_size + efi_mmap_size));
  648.     if (err)
  649.      return err;
  650.     real_mode_mem = get_virtual_current_address (ch);
  651.   }
  652.   efi_mmap_buf = (grub_uint8_t *) real_mode_mem + ctx.real_size;
  653.  
  654.   grub_dprintf ("linux", "real_mode_mem = %p\n",
  655.                 real_mode_mem);
  656.  
  657.   ctx.params = real_mode_mem;
  658.  
  659.   *ctx.params = linux_params;
  660.   ctx.params->cmd_line_ptr = ctx.real_mode_target + cl_offset;
  661.   grub_memcpy ((char *) ctx.params + cl_offset, linux_cmdline,
  662.            maximal_cmdline_size);
  663.  
  664.   grub_dprintf ("linux", "code32_start = %x\n",
  665.         (unsigned) ctx.params->code32_start);
  666.  
  667.   ctx.e820_num = 0;
  668.   if (grub_mmap_iterate (grub_linux_boot_mmap_fill, &ctx))
  669.     return grub_errno;
  670.   ctx.params->mmap_size = ctx.e820_num;
  671.  
  672. #ifdef GRUB_MACHINE_EFI
  673.   {
  674.     grub_efi_uintn_t efi_desc_size;
  675.     grub_size_t efi_mmap_target;
  676.     grub_efi_uint32_t efi_desc_version;
  677.     err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
  678.                      &efi_desc_size, &efi_desc_version);
  679.     if (err)
  680.       return err;
  681.    
  682.     /* Note that no boot services are available from here.  */
  683.     efi_mmap_target = ctx.real_mode_target
  684.       + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem);
  685.     /* Pass EFI parameters.  */
  686.     if (grub_le_to_cpu16 (ctx.params->version) >= 0x0208)
  687.       {
  688.     ctx.params->v0208.efi_mem_desc_size = efi_desc_size;
  689.     ctx.params->v0208.efi_mem_desc_version = efi_desc_version;
  690.     ctx.params->v0208.efi_mmap = efi_mmap_target;
  691.     ctx.params->v0208.efi_mmap_size = efi_mmap_size;
  692.  
  693. #ifdef __x86_64__
  694.     ctx.params->v0208.efi_mmap_hi = (efi_mmap_target >> 32);
  695. #endif
  696.       }
  697.     else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0206)
  698.       {
  699.     ctx.params->v0206.efi_mem_desc_size = efi_desc_size;
  700.     ctx.params->v0206.efi_mem_desc_version = efi_desc_version;
  701.     ctx.params->v0206.efi_mmap = efi_mmap_target;
  702.     ctx.params->v0206.efi_mmap_size = efi_mmap_size;
  703.       }
  704.     else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0204)
  705.       {
  706.     ctx.params->v0204.efi_mem_desc_size = efi_desc_size;
  707.     ctx.params->v0204.efi_mem_desc_version = efi_desc_version;
  708.     ctx.params->v0204.efi_mmap = efi_mmap_target;
  709.     ctx.params->v0204.efi_mmap_size = efi_mmap_size;
  710.       }
  711.   }
  712. #endif
  713.  
  714.   /* FIXME.  */
  715.   /*  asm volatile ("lidt %0" : : "m" (idt_desc)); */
  716.   state.ebp = state.edi = state.ebx = 0;
  717.   state.esi = ctx.real_mode_target;
  718.   state.esp = ctx.real_mode_target;
  719.   state.eip = ctx.params->code32_start;
  720.   return grub_relocator32_boot (relocator, state, 0);
  721. }
  722.  
  723. static grub_err_t
  724. grub_linux_unload (void)
  725. {
  726.   grub_dl_unref (my_mod);
  727.   loaded = 0;
  728.   grub_free (linux_cmdline);
  729.   linux_cmdline = 0;
  730.   return GRUB_ERR_NONE;
  731. }
  732.  
  733. static grub_err_t
  734. grub_cmd_mylinux (grub_command_t cmd __attribute__ ((unused)),
  735.         int argc, char *argv[])
  736. {
  737.   grub_file_t file = 0;
  738.   struct linux_kernel_header lh;
  739.   grub_uint8_t setup_sects;
  740.   grub_size_t real_size, prot_size, prot_file_size;
  741.   grub_ssize_t len;
  742.   int i;
  743.   grub_size_t align, min_align;
  744.   int relocatable;
  745.   grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
  746.  
  747.   grub_dl_ref (my_mod);
  748.  
  749.   if (argc == 0)
  750.     {
  751.       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  752.       goto fail;
  753.     }
  754.  
  755.   grub_printf ("%s (%s)\n", "Hello from my linux", argv[0]);
  756.  
  757.   file = grub_file_open (argv[0]);
  758.   if (! file)
  759.     goto fail;
  760.  
  761.   if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
  762.     {
  763.       if (!grub_errno)
  764.     grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  765.             argv[0]);
  766.       goto fail;
  767.     }
  768.  
  769.   if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
  770.     {
  771.       grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
  772.       goto fail;
  773.     }
  774.  
  775.   if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
  776.     {
  777.       grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
  778.       goto fail;
  779.     }
  780.  
  781.   /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
  782.      still not support 32-bit boot.  */
  783.   if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_MAGIC_SIGNATURE)
  784.       || grub_le_to_cpu16 (lh.version) < 0x0203)
  785.     {
  786.       grub_error (GRUB_ERR_BAD_OS, "version too old for 32-bit boot"
  787. #ifdef GRUB_MACHINE_PCBIOS
  788.           " (try with `linux16')"
  789. #endif
  790.           );
  791.       goto fail;
  792.     }
  793.  
  794.   if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
  795.     {
  796.       grub_error (GRUB_ERR_BAD_OS, "zImage doesn't support 32-bit boot"
  797. #ifdef GRUB_MACHINE_PCBIOS
  798.           " (try with `linux16')"
  799. #endif
  800.           );
  801.       goto fail;
  802.     }
  803.  
  804.   if (grub_le_to_cpu16 (lh.version) >= 0x0206)
  805.     maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
  806.   else
  807.     maximal_cmdline_size = 256;
  808.  
  809.   if (maximal_cmdline_size < 128)
  810.     maximal_cmdline_size = 128;
  811.  
  812.   setup_sects = lh.setup_sects;
  813.  
  814.   /* If SETUP_SECTS is not set, set it to the default (4).  */
  815.   if (! setup_sects)
  816.     setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
  817.  
  818.   real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
  819.   prot_file_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
  820.  
  821.   if (grub_le_to_cpu16 (lh.version) >= 0x205
  822.       && lh.kernel_alignment != 0
  823.       && ((lh.kernel_alignment - 1) & lh.kernel_alignment) == 0)
  824.     {
  825.       for (align = 0; align < 32; align++)
  826.     if (grub_le_to_cpu32 (lh.kernel_alignment) & (1 << align))
  827.       break;
  828.       relocatable = grub_le_to_cpu32 (lh.relocatable);
  829.     }
  830.   else
  831.     {
  832.       align = 0;
  833.       relocatable = 0;
  834.     }
  835.    
  836.   if (grub_le_to_cpu16 (lh.version) >= 0x020a)
  837.     {
  838.       min_align = lh.min_alignment;
  839.       prot_size = grub_le_to_cpu32 (lh.init_size);
  840.       prot_init_space = page_align (prot_size);
  841.       if (relocatable)
  842.     preferred_address = grub_le_to_cpu64 (lh.pref_address);
  843.       else
  844.     preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
  845.     }
  846.   else
  847.     {
  848.       min_align = align;
  849.       prot_size = prot_file_size;
  850.       preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
  851.       /* Usually, the compression ratio is about 50%.  */
  852.       prot_init_space = page_align (prot_size) * 3;
  853.     }
  854.  
  855.   if (allocate_pages (prot_size, &align,
  856.               min_align, relocatable,
  857.               preferred_address))
  858.     goto fail;
  859.  
  860.   grub_memset (&linux_params, 0, sizeof (linux_params));
  861.   grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
  862.  
  863.   linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
  864.   linux_params.kernel_alignment = (1 << align);
  865.   linux_params.ps_mouse = linux_params.padding10 =  0;
  866.  
  867.   len = sizeof (linux_params) - sizeof (lh);
  868.   if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
  869.     {
  870.       if (!grub_errno)
  871.     grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  872.             argv[0]);
  873.       goto fail;
  874.     }
  875.  
  876.   linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
  877.  
  878.   /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
  879.      and otherwise ignored.  */
  880.   linux_params.cl_magic = GRUB_LINUX_CL_MAGIC;
  881.   linux_params.cl_offset = 0x1000;
  882.  
  883.   linux_params.ramdisk_image = 0;
  884.   linux_params.ramdisk_size = 0;
  885.  
  886.   linux_params.heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
  887.   linux_params.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
  888.  
  889.   /* These are not needed to be precise, because Linux uses these values
  890.      only to raise an error when the decompression code cannot find good
  891.      space.  */
  892.   linux_params.ext_mem = ((32 * 0x100000) >> 10);
  893.   linux_params.alt_mem = ((32 * 0x100000) >> 10);
  894.  
  895.   /* Ignored by Linux.  */
  896.   linux_params.video_page = 0;
  897.  
  898.   /* Only used when `video_mode == 0x7', otherwise ignored.  */
  899.   linux_params.video_ega_bx = 0;
  900.  
  901.   linux_params.font_size = 16; /* XXX */
  902.  
  903. #ifdef GRUB_MACHINE_EFI
  904. #ifdef __x86_64__
  905.   if (grub_le_to_cpu16 (linux_params.version) < 0x0208 &&
  906.       ((grub_addr_t) grub_efi_system_table >> 32) != 0)
  907.     return grub_error(GRUB_ERR_BAD_OS,
  908.               "kernel does not support 64-bit addressing");
  909. #endif
  910.  
  911.   if (grub_le_to_cpu16 (linux_params.version) >= 0x0208)
  912.     {
  913.       linux_params.v0208.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
  914.       linux_params.v0208.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
  915. #ifdef __x86_64__
  916.       linux_params.v0208.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
  917. #endif
  918.     }
  919.   else if (grub_le_to_cpu16 (linux_params.version) >= 0x0206)
  920.     {
  921.       linux_params.v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
  922.       linux_params.v0206.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
  923.     }
  924.   else if (grub_le_to_cpu16 (linux_params.version) >= 0x0204)
  925.     {
  926.       linux_params.v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
  927.       linux_params.v0204.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
  928.     }
  929. #endif
  930.  
  931.   /* The other parameters are filled when booting.  */
  932.  
  933.   grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
  934.  
  935.   grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
  936.         (unsigned) real_size, (unsigned) prot_size);
  937.  
  938.   /* Look for memory size and video mode specified on the command line.  */
  939.   linux_mem_size = 0;
  940.   for (i = 1; i < argc; i++)
  941. #ifdef GRUB_MACHINE_PCBIOS
  942.     if (grub_memcmp (argv[i], "vga=", 4) == 0)
  943.       {
  944.     /* Video mode selection support.  */
  945.     char *val = argv[i] + 4;
  946.     unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
  947.     struct grub_vesa_mode_table_entry *linux_mode;
  948.     grub_err_t err;
  949.     char *buf;
  950.  
  951.     grub_dl_load ("vbe");
  952.  
  953.     if (grub_strcmp (val, "normal") == 0)
  954.       vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
  955.     else if (grub_strcmp (val, "ext") == 0)
  956.       vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
  957.     else if (grub_strcmp (val, "ask") == 0)
  958.       {
  959.         grub_puts_ (N_("Legacy `ask' parameter no longer supported."));
  960.  
  961.         /* We usually would never do this in a loader, but "vga=ask" means user
  962.            requested interaction, so it can't hurt to request keyboard input.  */
  963.         grub_wait_after_message ();
  964.  
  965.         goto fail;
  966.       }
  967.     else
  968.       vid_mode = (grub_uint16_t) grub_strtoul (val, 0, 0);
  969.  
  970.     switch (vid_mode)
  971.       {
  972.       case 0:
  973.       case GRUB_LINUX_VID_MODE_NORMAL:
  974.         grub_env_set ("gfxpayload", "text");
  975.         grub_printf_ (N_("%s is deprecated. "
  976.                  "Use set gfxpayload=%s before "
  977.                  "linux command instead.\n"),
  978.               argv[i], "text");
  979.         break;
  980.  
  981.       case 1:
  982.       case GRUB_LINUX_VID_MODE_EXTENDED:
  983.         /* FIXME: support 80x50 text. */
  984.         grub_env_set ("gfxpayload", "text");
  985.         grub_printf_ (N_("%s is deprecated. "
  986.                  "Use set gfxpayload=%s before "
  987.                  "linux command instead.\n"),
  988.               argv[i], "text");
  989.         break;
  990.       default:
  991.         /* Ignore invalid values.  */
  992.         if (vid_mode < GRUB_VESA_MODE_TABLE_START ||
  993.         vid_mode > GRUB_VESA_MODE_TABLE_END)
  994.           {
  995.         grub_env_set ("gfxpayload", "text");
  996.         /* TRANSLATORS: "x" has to be entered in, like an identifier,
  997.            so please don't use better Unicode codepoints.  */
  998.         grub_printf_ (N_("%s is deprecated. VGA mode %d isn't recognized. "
  999.                  "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] "
  1000.                  "before linux command instead.\n"),
  1001.                  argv[i], vid_mode);
  1002.         break;
  1003.           }
  1004.  
  1005.         linux_mode = &grub_vesa_mode_table[vid_mode
  1006.                            - GRUB_VESA_MODE_TABLE_START];
  1007.  
  1008.         buf = grub_xasprintf ("%ux%ux%u,%ux%u",
  1009.                  linux_mode->width, linux_mode->height,
  1010.                  linux_mode->depth,
  1011.                  linux_mode->width, linux_mode->height);
  1012.         if (! buf)
  1013.           goto fail;
  1014.  
  1015.         grub_printf_ (N_("%s is deprecated. "
  1016.                  "Use set gfxpayload=%s before "
  1017.                  "linux command instead.\n"),
  1018.              argv[i], buf);
  1019.         err = grub_env_set ("gfxpayload", buf);
  1020.         grub_free (buf);
  1021.         if (err)
  1022.           goto fail;
  1023.       }
  1024.       }
  1025.     else
  1026. #endif /* GRUB_MACHINE_PCBIOS */
  1027.     if (grub_memcmp (argv[i], "mem=", 4) == 0)
  1028.       {
  1029.     char *val = argv[i] + 4;
  1030.  
  1031.     linux_mem_size = grub_strtoul (val, &val, 0);
  1032.  
  1033.     if (grub_errno)
  1034.       {
  1035.         grub_errno = GRUB_ERR_NONE;
  1036.         linux_mem_size = 0;
  1037.       }
  1038.     else
  1039.       {
  1040.         int shift = 0;
  1041.  
  1042.         switch (grub_tolower (val[0]))
  1043.           {
  1044.           case 'g':
  1045.         shift += 10;
  1046.         /* FALLTHROUGH */
  1047.           case 'm':
  1048.         shift += 10;
  1049.         /* FALLTHROUGH */
  1050.           case 'k':
  1051.         shift += 10;
  1052.         /* FALLTHROUGH */
  1053.           default:
  1054.         break;
  1055.           }
  1056.  
  1057.         /* Check an overflow.  */
  1058.         if (linux_mem_size > (~0UL >> shift))
  1059.           linux_mem_size = 0;
  1060.         else
  1061.           linux_mem_size <<= shift;
  1062.       }
  1063.       }
  1064.     else if (grub_memcmp (argv[i], "quiet", sizeof ("quiet") - 1) == 0)
  1065.       {
  1066.     linux_params.loadflags |= GRUB_LINUX_FLAG_QUIET;
  1067.       }
  1068.  
  1069.   /* Create kernel command line.  */
  1070.   linux_cmdline = grub_zalloc (maximal_cmdline_size + 1);
  1071.   if (!linux_cmdline)
  1072.     goto fail;
  1073.   grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
  1074.   grub_create_loader_cmdline (argc, argv,
  1075.                   linux_cmdline
  1076.                   + sizeof (LINUX_IMAGE) - 1,
  1077.                   maximal_cmdline_size
  1078.                   - (sizeof (LINUX_IMAGE) - 1));
  1079.   if(appended_args_count > 0)
  1080.   { // Append our command line args)
  1081.     //find offset in `linux_cmdline` to begin appending
  1082.     unsigned offset = grub_strlen(linux_cmdline);
  1083.     if(offset + 2 < maximal_cmdline_size)
  1084.     {
  1085.       linux_cmdline[offset] = ' '; // Replase 0 -> space to append new args
  1086.       grub_create_loader_cmdline(appended_args_count, appended_args,
  1087.         linux_cmdline + offset + 1, maximal_cmdline_size - offset - 2);
  1088.     }
  1089.   }// That's all falks)
  1090.  
  1091.   len = prot_file_size;
  1092.   if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
  1093.     grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  1094.         argv[0]);
  1095.  
  1096.   if (grub_errno == GRUB_ERR_NONE)
  1097.     {
  1098.       grub_loader_set (grub_linux_boot, grub_linux_unload,
  1099.                0 /* set noreturn=0 in order to avoid grub_console_fini() */);
  1100.       loaded = 1;
  1101.     }
  1102.  
  1103.  fail:
  1104.  
  1105.   if (file)
  1106.     grub_file_close (file);
  1107.  
  1108.   if (grub_errno != GRUB_ERR_NONE)
  1109.     {
  1110.       grub_dl_unref (my_mod);
  1111.       loaded = 0;
  1112.     }
  1113.  
  1114.   return grub_errno;
  1115. }
  1116.  
  1117. static grub_err_t
  1118. grub_cmd_myinitrd (grub_command_t cmd __attribute__ ((unused)),
  1119.          int argc, char *argv[])
  1120. {
  1121.   grub_size_t size = 0, aligned_size = 0;
  1122.   grub_addr_t addr_min, addr_max;
  1123.   grub_addr_t addr;
  1124.   grub_err_t err;
  1125.   struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
  1126.  
  1127.   if (argc == 0)
  1128.     {
  1129.       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  1130.       goto fail;
  1131.     }
  1132.  
  1133.   if (! loaded)
  1134.     {
  1135.       grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
  1136.       goto fail;
  1137.     }
  1138.  
  1139.   grub_printf ("%s (%s)\n", "Hello from my initrd", argv[0]);
  1140.  
  1141.   if (grub_initrd_init (argc, argv, &initrd_ctx))
  1142.     goto fail;
  1143.  
  1144.   size = grub_get_initrd_size (&initrd_ctx);
  1145.   aligned_size = ALIGN_UP (size, 4096);
  1146.  
  1147.   /* Get the highest address available for the initrd.  */
  1148.   if (grub_le_to_cpu16 (linux_params.version) >= 0x0203)
  1149.     {
  1150.       addr_max = grub_cpu_to_le32 (linux_params.initrd_addr_max);
  1151.  
  1152.       /* XXX in reality, Linux specifies a bogus value, so
  1153.      it is necessary to make sure that ADDR_MAX does not exceed
  1154.      0x3fffffff.  */
  1155.       if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
  1156.     addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
  1157.     }
  1158.   else
  1159.     addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
  1160.  
  1161.   if (linux_mem_size != 0 && linux_mem_size < addr_max)
  1162.     addr_max = linux_mem_size;
  1163.  
  1164.   /* Linux 2.3.xx has a bug in the memory range check, so avoid
  1165.      the last page.
  1166.      Linux 2.2.xx has a bug in the memory range check, which is
  1167.      worse than that of Linux 2.3.xx, so avoid the last 64kb.  */
  1168.   addr_max -= 0x10000;
  1169.  
  1170.   addr_min = (grub_addr_t) prot_mode_target + prot_init_space;
  1171.  
  1172.   /* Put the initrd as high as possible, 4KiB aligned.  */
  1173.   addr = (addr_max - aligned_size) & ~0xFFF;
  1174.  
  1175.   if (addr < addr_min)
  1176.     {
  1177.       grub_error (GRUB_ERR_OUT_OF_RANGE, "the initrd is too big");
  1178.       goto fail;
  1179.     }
  1180.  
  1181.   {
  1182.     grub_relocator_chunk_t ch;
  1183.     err = grub_relocator_alloc_chunk_align (relocator, &ch,
  1184.                         addr_min, addr, aligned_size,
  1185.                         0x1000,
  1186.                         GRUB_RELOCATOR_PREFERENCE_HIGH,
  1187.                         1);
  1188.     if (err)
  1189.       return err;
  1190.     initrd_mem = get_virtual_current_address (ch);
  1191.     initrd_mem_target = get_physical_target_address (ch);
  1192.   }
  1193.  
  1194.   if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
  1195.     goto fail;
  1196.  
  1197.   grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
  1198.         (unsigned) addr, (unsigned) size);
  1199.  
  1200.   linux_params.ramdisk_image = initrd_mem_target;
  1201.   linux_params.ramdisk_size = size;
  1202.   linux_params.root_dev = 0x0100; /* XXX */
  1203.  
  1204.  fail:
  1205.   grub_initrd_close (&initrd_ctx);
  1206.  
  1207.   return grub_errno;
  1208. }
  1209.  
  1210. static grub_command_t cmd_mylinux, cmd_myinitrd;
  1211. // END FROM loader/i386/linux.c
  1212.  
  1213. static grub_extcmd_t cmd;
  1214.  
  1215.  
  1216. GRUB_MOD_INIT(append)
  1217. {
  1218.   cmd = grub_register_extcmd("append", grub_cmd_append, 0, 0,
  1219.                   N_("Setup (or show) arguments to append to kernel command line."), 0);
  1220.  
  1221.   cmd_mylinux = grub_register_command("linux", grub_cmd_mylinux,
  1222.                      0, N_("Load Linux."));
  1223.   cmd_myinitrd = grub_register_command("initrd", grub_cmd_myinitrd,
  1224.                       0, N_("Load initrd."));
  1225.   my_mod = mod;
  1226. }
  1227.  
  1228. GRUB_MOD_FINI(append)
  1229. {
  1230.   grub_unregister_extcmd(cmd);
  1231.   grub_unregister_command(cmd_mylinux);
  1232.   grub_unregister_command(cmd_myinitrd);
  1233.   clean_args();
  1234. }
  1235.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement