/*
    Copyright 2000 (c) by Authors, Boris Lutz, Claudio Jeker
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.

    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.

    For further information, please visit http://www.tik.ee.ethz.ch/~topsy

    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Boot/ia32/Tools/CreateNetImg/CreateImage.c,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2911 $
    Last Date of Change:   $Date: 2007-03-07 14:27:12 +0100 (Mit, 07 Mär 2007) $  by: $Author: rnatau $

*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

/* XXX fix filepathes are ugly but we control the Makefile so this is OK
   Probably this should be changed to program arguments --cjeker 20010315 */ 
#define KERNEL "../../../../kernel.bin"
#define USER   "../../../../user.bin"
#define CORELOAD "../../LowCore/CoreLoad/CoreLoad.bin"

main()
{
	char		InfoBlock[512];	/* contains header and information records */
				//DDCommand[128],
				//SkipLen[16];
	int			i,
				SizeFile,
				ImgFile;
	long		len,
				CoreLen,
				KernelLen,
				UserLen;
	struct stat	st;


	/* Get the size of the images */
	if (stat(KERNEL, &st) == -1) {
		perror("Faild to stat kernel.bin");
		exit(1);
	}
	KernelLen = (unsigned long) st.st_size;
	if (stat(USER, &st) == -1) {
		perror("Faild to stat user.bin");
		exit(1);
	}
	UserLen = (unsigned long) st.st_size;
	if (stat(CORELOAD, &st) == -1) {
		perror("Faild to stat kernel.bin");
		exit(1);
	}
	CoreLen = (unsigned long) st.st_size;

				
	printf("The size of the images is:\n\tCore:\t%li\n\tKernel:\t%li\n\tUser:\t%li\n\n", CoreLen, KernelLen, UserLen);

	/* Header */
	InfoBlock[0]  = 0x36;		/* Magic-Number	*/
	InfoBlock[1]  = 0x13;
	InfoBlock[2]  = 0x03;
	InfoBlock[3]  = 0x1B;
	InfoBlock[4]  = 0x04;		/* Length of header (from MN to the end) */
	InfoBlock[5]  = 0x00;
	InfoBlock[6]  = 0x00;
	InfoBlock[7]  = 0x00;
	InfoBlock[8]  = 0x00;		/* Location in ds:bx format */
	InfoBlock[9]  = 0x00;
	InfoBlock[10] = 0x00;
	InfoBlock[11] = 0x8F;
	InfoBlock[12] = 0x00;		/* Execute address in cs:ip format */
	InfoBlock[13] = 0x00;
	InfoBlock[14] = 0x00;
	InfoBlock[15] = 0x10;
	/* Information record 1 (CoreLoad) */
	InfoBlock[16] = 0x04;				/* Flags (length, vendor, ...) */
	InfoBlock[17] = 0x00;
	InfoBlock[18] = 0x00;
	InfoBlock[19] = 0x00;
	InfoBlock[20] = 0x00;				/* Load address */
	InfoBlock[21] = 0x00;
	InfoBlock[22] = 0x01;
	InfoBlock[23] = 0x00;
	InfoBlock[24] = CoreLen & 0xFF;		/* Image length */
	InfoBlock[25] = (CoreLen >>  8) & 0xFF;
	InfoBlock[26] = (CoreLen >> 16) & 0xFF;
	InfoBlock[27] = (CoreLen >> 24);
	InfoBlock[28] = CoreLen & 0xFF;		/* Memory length */
	InfoBlock[29] = (CoreLen >>  8) & 0xFF;
	InfoBlock[30] = (CoreLen >> 16) & 0xFF;
	InfoBlock[31] = (CoreLen >> 24);
	/* Information record 2 (Kernel) */
	InfoBlock[32] = 0x04;				/* Flags (length, vendor, ...) */
	InfoBlock[33] = 0x00;
	InfoBlock[34] = 0x00;
	InfoBlock[35] = 0x00;
	InfoBlock[36] = 0x00;				/* Load address */
	InfoBlock[37] = 0x00;
	InfoBlock[38] = 0x02;
	InfoBlock[39] = 0x00;
	InfoBlock[40] = KernelLen & 0xFF;	/* Image length */
	InfoBlock[41] = (KernelLen >>  8) & 0xFF;
	InfoBlock[42] = (KernelLen >> 16) & 0xFF;
	InfoBlock[43] = (KernelLen >> 24);
	InfoBlock[44] = KernelLen & 0xFF;	/* Memory length */
	InfoBlock[45] = (KernelLen >>  8) & 0xFF;
	InfoBlock[46] = (KernelLen >> 16) & 0xFF;
	InfoBlock[47] = (KernelLen >> 24);
	/* Information record 3 (User) */
	InfoBlock[48] = 0x04;				/* Flags (length, vendor, ...) */
	InfoBlock[49] = 0x00;
	InfoBlock[50] = 0x00;
	InfoBlock[51] = 0x04;
	InfoBlock[52] = 0x00;				/* Load address */
	InfoBlock[53] = 0x00;
	InfoBlock[54] = 0x09;
	InfoBlock[55] = 0x00;
	InfoBlock[56] = UserLen & 0xFF;		/* Image length */
	InfoBlock[57] = (UserLen >>  8) & 0xFF;
	InfoBlock[58] = (UserLen >> 16) & 0xFF;
	InfoBlock[59] = (UserLen >> 24);
	InfoBlock[60] = UserLen & 0xFF;		/* Memory length */
	InfoBlock[61] = (UserLen >>  8) & 0xFF;
	InfoBlock[62] = (UserLen >> 16) & 0xFF;
	InfoBlock[63] = (UserLen >> 24);
	

	/* Fill the rest of the 512Bytes with zeros */

	for (i = 64; i < 512; i++) {
		InfoBlock[i] = 0;
	}


	ImgFile = open ("./header.bin", O_WRONLY | O_CREAT | O_TRUNC, 0644);
	len = write (ImgFile, InfoBlock, 512);
	if (len != 512) exit (-1);
	close (ImgFile);

	/* ALL DD COMANDS ARE DONE BY THE MAKEFILE */
	/*
	strcpy (DDCommand, "/bin/dd if=Header.bin of=BootImg obs=512");
	printf ("adding header to boot image: %s\n", DDCommand);
	system (DDCommand);

	strcpy (DDCommand, "/bin/dd if=CoreLoad.bin of=BootImg obs=512 seek=1");
	printf ("adding loader to boot image: %s\n", DDCommand);
	system (DDCommand);

	strcpy (DDCommand, "/bin/dd if=kernel.bin of=BootImg obs=512 seek=");
	sprintf(SkipLen, "%li", CoreLen / 512L + 1L );
	strcat (DDCommand, SkipLen);
	printf ("adding kernel to boot image: %s\n", DDCommand);
	system (DDCommand);

	strcpy (DDCommand, "/bin/dd if=user.bin of=BootImg obs=512 seek=");
	sprintf(SkipLen, "%li", KernelLen / 512L + CoreLen / 512L + 1L );
	strcat (DDCommand, SkipLen);
	printf ("adding user to boot image: %s\n", DDCommand);
	system (DDCommand);

	strcpy (DDCommand, "/bin/dd if=/dev/zero of=BootImg obs=512 count=0 seek=");
	sprintf(SkipLen, "%li", KernelLen / 512L + CoreLen / 512L + UserLen / 512L + 1L );
	strcat (DDCommand, SkipLen);
	printf ("rounding up to 512Bytes: %s\n", DDCommand);
	system (DDCommand);

	*/
}

