mirror of
				https://git.proxmox.com/git/grub2
				synced 2025-11-04 03:55:15 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			223 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
  * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2013  Free Software Foundation, Inc.
 | 
						|
  *
 | 
						|
  * GRUB is free software: you can redistribute it and/or modify
 | 
						|
  * it under the terms of the GNU General Public License as published by
 | 
						|
  * the Free Software Foundation, either version 3 of the License, or
 | 
						|
  * (at your option) any later version.
 | 
						|
  *
 | 
						|
  * GRUB is distributed in the hope that it will be useful,
 | 
						|
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
  * GNU General Public License for more details.
 | 
						|
  *
 | 
						|
  * You should have received a copy of the GNU General Public License
 | 
						|
  * along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
*/
 | 
						|
 | 
						|
#include <config.h>
 | 
						|
 | 
						|
#include <grub/util/install.h>
 | 
						|
#include <grub/emu/config.h>
 | 
						|
#include <grub/util/misc.h>
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
 | 
						|
#pragma GCC diagnostic ignored "-Wmissing-declarations"
 | 
						|
#include <argp.h>
 | 
						|
#pragma GCC diagnostic error "-Wmissing-prototypes"
 | 
						|
#pragma GCC diagnostic error "-Wmissing-declarations"
 | 
						|
 | 
						|
static char *rootdir = NULL, *subdir = NULL;
 | 
						|
static char *debug_image = NULL;
 | 
						|
 | 
						|
enum
 | 
						|
  {
 | 
						|
    OPTION_NET_DIRECTORY = 0x301,
 | 
						|
    OPTION_SUBDIR,
 | 
						|
    OPTION_DEBUG,
 | 
						|
    OPTION_DEBUG_IMAGE
 | 
						|
  };
 | 
						|
 | 
						|
static struct argp_option options[] = {
 | 
						|
  GRUB_INSTALL_OPTIONS,
 | 
						|
  {"net-directory", OPTION_NET_DIRECTORY, N_("DIR"),
 | 
						|
   0, N_("root directory of TFTP server"), 2},
 | 
						|
  {"subdir", OPTION_SUBDIR, N_("DIR"),
 | 
						|
   0, N_("relative subdirectory on network server"), 2},
 | 
						|
  {"debug", OPTION_DEBUG, 0, OPTION_HIDDEN, 0, 2},
 | 
						|
  {"debug-image", OPTION_DEBUG_IMAGE, N_("STRING"), OPTION_HIDDEN, 0, 2},
 | 
						|
  {0, 0, 0, 0, 0, 0}
 | 
						|
};
 | 
						|
 | 
						|
static error_t 
 | 
						|
argp_parser (int key, char *arg, struct argp_state *state)
 | 
						|
{
 | 
						|
  if (grub_install_parse (key, arg))
 | 
						|
    return 0;
 | 
						|
  switch (key)
 | 
						|
    {
 | 
						|
    case OPTION_NET_DIRECTORY:
 | 
						|
      free (rootdir);
 | 
						|
      rootdir = xstrdup (arg);
 | 
						|
      return 0;
 | 
						|
    case OPTION_SUBDIR:
 | 
						|
      free (subdir);
 | 
						|
      subdir = xstrdup (arg);
 | 
						|
      return 0;
 | 
						|
      /* This is an undocumented feature...  */
 | 
						|
    case OPTION_DEBUG:
 | 
						|
      verbosity++;
 | 
						|
      return 0;
 | 
						|
    case OPTION_DEBUG_IMAGE:
 | 
						|
      free (debug_image);
 | 
						|
      debug_image = xstrdup (arg);
 | 
						|
      return 0;
 | 
						|
 | 
						|
    case ARGP_KEY_ARG:
 | 
						|
    default:
 | 
						|
      return ARGP_ERR_UNKNOWN;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
struct argp argp = {
 | 
						|
  options, argp_parser, NULL,
 | 
						|
  "\v"N_("Prepares GRUB network boot images at net_directory/subdir "
 | 
						|
	 "assuming net_directory being TFTP root."), 
 | 
						|
  NULL, grub_install_help_filter, NULL
 | 
						|
};
 | 
						|
 | 
						|
static char *base;
 | 
						|
 | 
						|
static const struct
 | 
						|
{
 | 
						|
  const char *mkimage_target;
 | 
						|
  const char *netmodule;
 | 
						|
  const char *ext;
 | 
						|
} targets[GRUB_INSTALL_PLATFORM_MAX] =
 | 
						|
  {
 | 
						|
    [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386-pc-pxe", "pxe", ".0" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64-ieee1275-aout", "ofnet", ".img" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386-ieee1275", "ofnet", ".elf" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc-ieee1275", "ofnet", ".elf" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386-efi", "efinet", ".efi" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64-efi", "efinet", ".efi" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64-efi", "efinet", ".efi" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm-efi", "efinet", ".efi" },
 | 
						|
    [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64-efi", "efinet", ".efi" }
 | 
						|
  };
 | 
						|
 | 
						|
static void
 | 
						|
process_input_dir (const char *input_dir, enum grub_install_plat platform)
 | 
						|
{
 | 
						|
  char *platsub = grub_install_get_platform_name (platform);
 | 
						|
  char *grubdir = grub_util_path_concat (3, rootdir, subdir, platsub);
 | 
						|
  char *load_cfg = grub_util_path_concat (2, grubdir, "load.cfg");
 | 
						|
  char *prefix;
 | 
						|
  char *output;
 | 
						|
  char *grub_cfg;
 | 
						|
  FILE *cfg;
 | 
						|
 | 
						|
  grub_install_copy_files (input_dir, base, platform);
 | 
						|
  grub_util_unlink (load_cfg);
 | 
						|
 | 
						|
  if (debug_image)
 | 
						|
    {
 | 
						|
      FILE *f = grub_util_fopen (load_cfg, "wb");
 | 
						|
      if (!f)
 | 
						|
	grub_util_error (_("cannot open `%s': %s"), load_cfg,
 | 
						|
			 strerror (errno));
 | 
						|
      fprintf (f, "set debug='%s'\n", debug_image);
 | 
						|
      fclose (f);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      free (load_cfg);
 | 
						|
      load_cfg = 0;
 | 
						|
    }
 | 
						|
 | 
						|
  prefix = xasprintf ("/%s", subdir);
 | 
						|
  if (!targets[platform].mkimage_target)
 | 
						|
    grub_util_error (_("unsupported platform %s"), platsub);
 | 
						|
 | 
						|
  grub_cfg = grub_util_path_concat (2, grubdir, "grub.cfg");
 | 
						|
  cfg = grub_util_fopen (grub_cfg, "wb");
 | 
						|
  if (!cfg)
 | 
						|
    grub_util_error (_("cannot open `%s': %s"), grub_cfg,
 | 
						|
		     strerror (errno));
 | 
						|
  fprintf (cfg, "source %s/grub.cfg", subdir);
 | 
						|
  fclose (cfg);
 | 
						|
 | 
						|
  grub_install_push_module (targets[platform].netmodule);
 | 
						|
 | 
						|
  output = grub_util_path_concat_ext (2, grubdir, "core", targets[platform].ext);
 | 
						|
  grub_install_make_image_wrap (input_dir, prefix, output,
 | 
						|
				0, load_cfg,
 | 
						|
				targets[platform].mkimage_target, 0);
 | 
						|
  grub_install_pop_module ();
 | 
						|
 | 
						|
  /* TRANSLATORS: First %s is replaced by platform name. Second one by filename.  */
 | 
						|
  printf (_("Netboot directory for %s created. Configure your DHCP server to point to %s\n"),
 | 
						|
	  platsub, output);
 | 
						|
 | 
						|
  free (platsub);
 | 
						|
  free (output);
 | 
						|
  free (prefix);
 | 
						|
  free (grub_cfg);
 | 
						|
  free (grubdir);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int
 | 
						|
main (int argc, char *argv[])
 | 
						|
{
 | 
						|
  const char *pkglibdir;
 | 
						|
 | 
						|
  grub_util_host_init (&argc, &argv);
 | 
						|
  grub_util_disable_fd_syncs ();
 | 
						|
  rootdir = xstrdup ("/srv/tftp");
 | 
						|
  pkglibdir = grub_util_get_pkglibdir ();
 | 
						|
 | 
						|
  subdir = grub_util_path_concat (2, GRUB_BOOT_DIR_NAME, GRUB_DIR_NAME);
 | 
						|
 | 
						|
  argp_parse (&argp, argc, argv, 0, 0, 0);
 | 
						|
 | 
						|
  base = grub_util_path_concat (2, rootdir, subdir);
 | 
						|
  /* Create the GRUB directory if it is not present.  */
 | 
						|
 | 
						|
  grub_install_mkdir_p (base);
 | 
						|
 | 
						|
  grub_install_push_module ("tftp");
 | 
						|
 | 
						|
  if (!grub_install_source_directory)
 | 
						|
    {
 | 
						|
      enum grub_install_plat plat;
 | 
						|
 | 
						|
      for (plat = 0; plat < GRUB_INSTALL_PLATFORM_MAX; plat++)
 | 
						|
	if (targets[plat].mkimage_target)
 | 
						|
	  {
 | 
						|
	    char *platdir = grub_util_path_concat (2, pkglibdir,
 | 
						|
						   grub_install_get_platform_name (plat));
 | 
						|
 | 
						|
	    grub_util_info ("Looking for `%s'", platdir);
 | 
						|
 | 
						|
	    if (!grub_util_is_directory (platdir))
 | 
						|
	      {
 | 
						|
		free (platdir);
 | 
						|
		continue;
 | 
						|
	      }
 | 
						|
	    process_input_dir (platdir, plat);
 | 
						|
	  }
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      enum grub_install_plat plat;
 | 
						|
      plat = grub_install_get_target (grub_install_source_directory);
 | 
						|
      process_input_dir (grub_install_source_directory, plat);
 | 
						|
    }
 | 
						|
  return 0;
 | 
						|
}
 |