/*
	Copyright (c) 1996-1997 Swiss Federal Institute of Technology, 
	Computer Engineering and Networks Laboratory. All rights reserved.
 
	TOPSY - A Teachable Operating System. 
		Implementation of a tiny and simple micro kernel for
		teaching purposes.
 
	Permission to use, copy, modify, and distribute this software and its
	documentation for any purpose, without fee, and without written 
	agreement is hereby granted, provided that the above copyright notice 
	and the following two paragraphs appear in all copies of this software.
 
 
	
	File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Startup/unix/start.c,v $
 	Author(s):             George Fankhauser
 	Affiliation:           ETH Zurich, TIK
 	Version:               $Revision: 2936 $
 	Creation Date:         
 	Last Date of Change:   $Date: 2007-03-21 15:23:42 +0100 (Mit, 21 Mär 2007) $      by: $Author: baderma $
	
	
*/

#include "MemoryLayout.h"
#include "MMMapping.h"
#include "Memory.h"
#include "Error.h"
#include "Unix.h"
#include "Startup.h"
#include "Threads.h"

#include <stdlib.h>   // system/exec...

static SegMapDescriptor segmapdesc;
SegMapPtr segmap;

int main()
{
  int user_size = 0, fd_user = 0, fd_sym = 0, tmp = 0;
  char c = 0;
  char symBuf[32];
  Address userMain;
  sigset_t mask;

  // load user process from binary image file (generated by objcopy)
  fd_user = open("./user.bin", O_RDONLY);
  if (fd_user == -1)
  {
    ERROR("can't open user image [user.bin]\n");
    exit(-1);
  }

  // size user
  user_size = 0;
  while (read(fd_user, &c, 1) != 0)
  {
    user_size++;
  }

  // make room for user space
  if (brk((void*)USERBRKAT + USERMEM) != 0)
  {
    ERROR("brk failed");
  }
  physBase = (int)mmap((char*)USERBRKAT, user_size,
                       PROT_READ|PROT_WRITE|PROT_EXEC,
                       MAP_FIXED|MAP_PRIVATE, fd_user, 0) - USERSTART;
  //printf("topsy user memory @ 0x%08x\n\n", physBase+USERSTART);

  // for nm to get symbol of user's "main()" program...
  system("rm ./user.sym");
  system("nm -p user | grep 'T main' > user.sym");
  fd_sym = open("./user.sym", O_RDONLY);
  if (fd_sym == -1)
  {
    ERROR("can't open user symbol file [user.sym]\n");
    exit(-1);
  }
  read(fd_sym, symBuf, sizeof(symBuf)-1);
  tmp = sscanf(symBuf, "%d T main", &userMain);
  if (tmp != 1)
  {
    ERROR("can't read from user symbol file [user.sym]\n");
    exit(-1);
  }
  close(fd_sym);

#warning ______________bootStackBottom_______
  // these 0x1000 sized regions are dummies for the unix port...
  bootStackBottom = (int)(physBase + BOOTSTACKBOTTOM);
  segmapdesc.kernelCodeSize = 0x1000;
  segmapdesc.kernelCodeStart = (Address)bootStackBottom + BOOTSTACKSIZE;
  segmapdesc.kernelDataSize = 0x1000;
  segmapdesc.kernelDataStart = (Address)segmapdesc.kernelCodeStart +
                               segmapdesc.kernelCodeSize;
  segmapdesc.userCodeSize = user_size;
  segmapdesc.userCodeStart = (Address)physBase + USERSTART;
  segmapdesc.userDataSize = 0x1000;
  segmapdesc.userDataStart = (Address)physBase + USERSTART + user_size;
  segmapdesc.userJumpAddress = (Address)userMain; /* from nm output" */
  segmapdesc.userLoadedInKernelAt = 0;
  segmap = &segmapdesc;

  topsyMain();  // as of version 1.2 this is the new main function name
}

// __main() {}  // depending on libraries this is needed (native) or not (unix)
#ifdef __gnu_ld__
void _start()
{
  main();
}// dep. on ld this is needed (gnu ld) or not (sun ld)
#endif
