/*
* linux/tools/build.c
*
* (C) 1991 Linus Torvalds
*/

/*
* This file builds a disk-image from three different files:
*
* - bootsect: max 510 bytes of 8086 machine code, loads the rest
* - setup: max 4 sectors of 8086 machine code, sets up system parm
* - system: 80386 code for actual system
*
* It does some checking that all files are of the correct type, and
* just writes the result to stdout, removing headers and padding to
* the right amount. It also writes some system data to stderr.
*/
/*
* óͬĳдӳļ
*
* - bootsectļ8086 Ϊ510 ֽڣڼ
* - setupļ8086 Ϊ4 ϵͳ
* - systemʵϵͳ80386 롣
*
* óȼгģǷȷնʾ
* ȻɾģͷȷĳȡóҲὫһЩϵͳдstderr
*/

/*
* Changes by tytso to allow root device specification
*/
/*
* tytso Ըó޸ģָļ豸
*/

#include <stdio.h> /* fprintf */	/* ʹеfprintf() */
#include <string.h>		/* ַ */
#include <stdlib.h> /* contains exit */	/* exit() */
#include <sys/types.h> /* unistd.h needs this */	/* unistd.h ʹ */
#include <sys/stat.h>		/* ļ״̬Ϣṹ */
#include <linux/fs.h>		/* ļϵͳ */
#include <unistd.h> /* contains read/write */	/* read()/write() */
#include <fcntl.h>		/* ļģʽų */

#define MINIX_HEADER 32		// minix ģͷΪ32 ֽڡ
#define GCC_HEADER 1024		// GCC ͷϢΪ1024 ֽڡ

#define SYS_SIZE 0x2000		// system ļ(ֽΪSYS_SIZE*16=128KB)


#define DEFAULT_MAJOR_ROOT 3	// Ĭϸ豸豸 - 3Ӳ̣
#define DEFAULT_MINOR_ROOT 6	// Ĭϸ豸豸 - 62 Ӳ̵ĵ1 

/* max nr of sectors of setup: don't change unless you also change
* bootsect etc */
/* ָsetup ģռҪıֵҲıbootsect Ӧļ
#define SETUP_SECTS 4 // setup 󳤶Ϊ4 4*512 ֽڣ
*/
#define STRINGIFY(x) #x		// ڳʱʾбʾ

//// ʾϢֹ
void
die (char *str)
{
  fprintf (stderr, "%s\n", str);
  exit (1);
}

// ʾʹ÷˳
void
usage (void)
{
  die ("Usage: build bootsect setup system [rootdev] [> image]");
}

int
main (int argc, char **argv)
{
  int i, c, id;
  char buf[1024];
  char major_root, minor_root;
  struct stat sb;

// в4 5 ʾ÷˳
  if ((argc != 4) && (argc != 5))
    usage ();
// 5 ˵и豸
  if (argc == 5)
    {
// 豸("FLOPPY")ȡ豸ļ״̬ϢʾϢ˳
      if (strcmp (argv[4], "FLOPPY"))
	{
	  if (stat (argv[4], &sb))
	    {
	      perror (argv[4]);
	      die ("Couldn't stat root device.");
	    }
// ɹȡ豸״̬ṹе豸źʹ豸š
	  major_root = MAJOR (sb.st_rdev);
	  minor_root = MINOR (sb.st_rdev);
	}
      else
	{
// 豸źʹ豸ȡ0
	  major_root = 0;
	  minor_root = 0;
	}
// ֻ4 豸źʹ豸ŵϵͳĬϵĸ豸
    }
  else
    {
      major_root = DEFAULT_MAJOR_ROOT;
      minor_root = DEFAULT_MINOR_ROOT;

    }
// ڱ׼նʾѡĸ豸豸š
  fprintf (stderr, "Root device is (%d, %d)\n", major_root, minor_root);
// 豸Ų2()3(Ӳ)Ҳ0(ȡϵͳĬϸ豸)ʾϢ˳
  if ((major_root != 2) && (major_root != 3) && (major_root != 0))
    {
      fprintf (stderr, "Illegal root device (major = %d)\n", major_root);
      die ("Bad root device --- major #");
    }
// ʼbuf ȫ0
  for (i = 0; i < sizeof buf; i++)
    buf[i] = 0;
// ֻʽ򿪲1 ָļ(bootsect)ʾϢ˳
  if ((id = open (argv[1], O_RDONLY, 0)) < 0)
    die ("Unable to open 'boot'");
// ȡļеminix ִͷϢ(μб˵)ʾϢ˳
  if (read (id, buf, MINIX_HEADER) != MINIX_HEADER)
    die ("Unable to read header of 'boot'");
// 0x0301 - minix ͷa_magic ħ0x10 - a_flag ִУ0x04 - a_cpu, Intel 8086 롣
  if (((long *) buf)[0] != 0x04100301)
    die ("Non-Minix header of 'boot'");
// жͷֶa_hdrlenֽڣǷȷֽûã0
  if (((long *) buf)[1] != MINIX_HEADER)
    die ("Non-Minix header of 'boot'");
// жݶγa_data ֶ(long)ǷΪ0
  if (((long *) buf)[3] != 0)
    die ("Illegal data segment in 'boot'");
// ж϶a_bss ֶ(long)ǷΪ0
  if (((long *) buf)[4] != 0)
    die ("Illegal bss in 'boot'");
// жִеa_entry ֶ(long)ǷΪ0
  if (((long *) buf)[5] != 0)
    die ("Non-Minix header of 'boot'");
// жϷűֶa_sym ǷΪ0
  if (((long *) buf)[7] != 0)
    die ("Illegal symbol table in 'boot'");
// ȡʵʴݣӦ÷ضȡֽΪ512 ֽڡ
  i = read (id, buf, sizeof buf);
  fprintf (stderr, "Boot sector %d bytes.\n", i);
  if (i != 512)
    die ("Boot block must be exactly 512 bytes");
// жboot 0x510 Ƿп־0xAA55
  if ((*(unsigned short *) (buf + 510)) != 0xAA55)
    die ("Boot block hasn't got boot flag (0xAA55)");
// 508509 ƫƴŵǸ豸š
  buf[508] = (char) minor_root;
  buf[509] = (char) major_root;
// boot 512 ֽڵд׼stdoutдֽԣʾϢ˳
  i = write (1, buf, 512);
  if (i != 512)
    die ("Write call failed");
// رbootsect ģļ
  close (id);


// ڿʼsetup ģ顣ֻʽ򿪸ģ飬ʾϢ˳
  if ((id = open (argv[2], O_RDONLY, 0)) < 0)
    die ("Unable to open 'setup'");
// ȡļеminix ִͷϢ(32 ֽ)ʾϢ˳
  if (read (id, buf, MINIX_HEADER) != MINIX_HEADER)
    die ("Unable to read header of 'setup'");
// 0x0301 - minix ͷa_magic ħ0x10 - a_flag ִУ0x04 - a_cpu, Intel 8086 롣
  if (((long *) buf)[0] != 0x04100301)
    die ("Non-Minix header of 'setup'");
// жͷֶa_hdrlenֽڣǷȷֽûã0
  if (((long *) buf)[1] != MINIX_HEADER)
    die ("Non-Minix header of 'setup'");
// жݶγa_data ֶ(long)ǷΪ0
  if (((long *) buf)[3] != 0)
    die ("Illegal data segment in 'setup'");
// ж϶a_bss ֶ(long)ǷΪ0
  if (((long *) buf)[4] != 0)
    die ("Illegal bss in 'setup'");
// жִеa_entry ֶ(long)ǷΪ0
  if (((long *) buf)[5] != 0)
    die ("Non-Minix header of 'setup'");
// жϷűֶa_sym ǷΪ0
  if (((long *) buf)[7] != 0)
    die ("Illegal symbol table in 'setup'");
// ȡִдݣд׼stdout
  for (i = 0; (c = read (id, buf, sizeof buf)) > 0; i += c)
    if (write (1, buf, c) != c)
      die ("Write call failed");
//رsetup ģļ
  close (id);
// setup ģ鳤ȴ4 ʾϢ˳
  if (i > SETUP_SECTS * 512)
    die ("Setup exceeds " STRINGIFY (SETUP_SECTS)
	 " sectors - rewrite build/boot/setup");
// ڱ׼stderr ʾsetup ļĳֵ
  fprintf (stderr, "Setup is %d bytes.\n", i);
// buf 㡣
  for (c = 0; c < sizeof (buf); c++)
    buf[c] = '\0';
// setup С4*512 ֽڣ\0 setup Ϊ4*512 ֽڡ
  while (i < SETUP_SECTS * 512)
    {
      c = SETUP_SECTS * 512 - i;
      if (c > sizeof (buf))
	c = sizeof (buf);
      if (write (1, buf, c) != c)
	die ("Write call failed");
      i += c;
    }

// 洦system ģ顣ֻʽ򿪸ļ
  if ((id = open (argv[3], O_RDONLY, 0)) < 0)
    die ("Unable to open 'system'");

// system ģGCC ʽļȶȡGCC ʽͷṹϢ(linux ִļҲøøʽ)
  if (read (id, buf, GCC_HEADER) != GCC_HEADER)
    die ("Unable to read header of 'system'");
// ýṹеִдڵֶa_entry ֵӦΪ0
  if (((long *) buf)[5] != 0)
    die ("Non-GCC header of 'system'");
// ȡִдݣд׼stdout
  for (i = 0; (c = read (id, buf, sizeof buf)) > 0; i += c)
    if (write (1, buf, c) != c)
      die ("Write call failed");
// رsystem ļstderr ϴӡsystem ֽ
  close (id);
  fprintf (stderr, "System is %d bytes.\n", i);
// system ݳȳSYS_SIZE ڣ128KB ֽڣʾϢ˳
  if (i > SYS_SIZE * 16)
    die ("System is too big");
  return (0);
}
