/* Init.c, Copyright (c) by Lukas Ruf, lr@lpr.ch, 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: /usr/drwho/vault/cvs/topsy/Topsy/Startup/ia32/Init.c,v $ Author(s): Lukas Ruf, lr@lpr.ch Affiliation: ETH Zuerich, TIK Version: $Revision: 1.4 $ Creation Date: Last Date of Change: $Date: 1999/12/13 21:48:32 $ by: $Author: ruf $ $Log: Init.c,v $ Revision 1.4 1999/12/13 21:48:32 ruf GNU General Public Licence Update Revision 1.3 1999/06/06 20:55:06 jeker putting everything together for Topsy 2.0 Revision 1.2 1999/05/20 15:08:41 jeker little changes for ia32 port Revision 1.1 1999/05/13 17:05:44 jeker Initial revision */ #include "Video.h" #include "TMClock.h" #include "Keyboard.h" #include "Tools.h" #include "string.h" #include "asm.h" #include "SupportAsm.h" #include "Exception.h" #include "MMHal.h" #include "CoreLoad.h" #include "BinaryFile.h" #include "Startup.h" /* Memory.h is only included for SegMapDescriptor features as this map is dynamically created during startup. */ #include "Memory.h" #include "MMMapping.h" #include "MemoryLayout.h" /* cpu.h is included in fact only for UADDR_BASE. This is for sure relativ to the K0SEG_BASE as the Kernel Data Segment includes the User Segment as well. */ #include "cpu.h" /* Concatenate: Concatenate chunks of bytes in Protected Mode. Linear Data Segment is needed. Please note, no controls on segment boundaries is performed... I lack time. :-) */ /* This concatenate routine implicates that the loaded chunks of byte all start with a leading binary file header: BinaryFileDesc, defined in BinaryFile.h. I do not use any predefined file format like a.out, as there would be more to be done (time) and there would be a waste of space and (parsing) time while loading. So I simply act on binary images.... */ #include "BinaryFile.h" #define ONETRACK 18*512 #define TRACKMAX 7 #define BLOCKSIZE 64*1024 #define BLOCKREMAIN BLOCKSIZE - TRACKMAX*ONETRACK /* create the structure SegMapDescriptor in this file. Use it via IOHal.h in every other function and the segmap. */ struct SegMapDescriptor_t SegMapDesc_i386; SegMapPtr segmap; static unsigned long TextSize = 0; // Size of Code Segment static unsigned long DataSize = 0; // Size of Data Segment /* A Starting address range is leaded by a struct as defined in BinaryFile.h. Every following Address range starts at previous+0x10000. In one 64KB-Block there are only TRACKMAX of Bytes stored within. The Address range is concatenated to the starting block, i.e. the starting block remains at the location specified. ptarget : location where the chunks are concatenated to. psource : starting location, normaly equals to ptarget, except user chunk */ static char Concatenate(void *ptarget, void *psource) { long i,j,k, tr; char *pt, *ps; BinFileDescPtr BFD; /* Header Structure, to concatenate all types, use Binary File Header */ pt = (char*)ptarget; ps = (char*)psource; /* avoid getting stupid by castings */ BFD = (BinFileDescPtr)psource; /* Map Header of file to chunk start */ if (strncmp((char*)MARKER,(char*)BFD->marker,(int)strlen(MARKER))) return 1; printf("\n"); /* I am esthete, even in program coding */ printf(" - Tracks: 0x%8x \n",(unsigned int)BFD->tracksize); printf(" - Code: 0x%8x \n",(unsigned int)BFD->codesize); printf(" - Data: 0x%8x \n",(unsigned int)BFD->datasize); tr = BFD->tracksize; j = 0; while (tr > 0) { for (k = 0; (k < TRACKMAX) && (tr > 0); k++) { for (i = 0; i < ONETRACK; i++) pt[j++] = *(ps+i); ps += ONETRACK; tr--; } ps+= BLOCKREMAIN; } return 0; } /* Generate the SegMapDescriptor as defined in Startup/Memory.h */ static void BuildSegMap() { Boolean userFound = FALSE; SegMapPtr SMD = &SegMapDesc_i386; /* just for typing ... */ /* Move User and Driver Code and Data to their appropriate places */ /* USER */ /* User Code and Data to the User Space, defined in Tospy/i386/cpu.h Concatenate User space in the User Load Address Range, as a funny bytecopy() call will move the User chunk to its appropriate location specified by UADDR_BASE. */ printf("Concatenate USER"); if (!Concatenate((void*)ULOAD_ADDR ,(void*)ULOAD_ADDR)) { printf(" - found at 0x%8x and concatenated to 0x%8x\n", (unsigned int)ULOAD_ADDR,(unsigned int)ULOAD_ADDR); userFound = TRUE; } else printf(" - not found at 0x%8x\n", (unsigned int)ULOAD_ADDR); /* DRIVER */ /* Drivers right after Kernel Code and Data, defined in Tospy/i386/cpu.h */ /* printf("Concatenate DRIVER"); if (!Concatenate((void*)TextSize+DataSize,(void*)DLOAD_ADDR)) printf(" - found at 0x%8x and concatenated to 0x%8x\n", (unsigned int)DLOAD_ADDR,(unsigned int)(TextSize+DataSize)); else printf(" - not found at 0x%8x\n", (unsigned int)DLOAD_ADDR); */ /* Create the Segment Descriptor Table dynamically */ /* KERNEL */ /* Kernel Code starts at location 64(dec) within the Kernel Code Segment */ SMD->kernelCodeStart = (Address)0x00; /* Note: TextSize is rounded to page boundary during assignments... :-) */ SMD->kernelCodeSize = TextSize; /* exactly above the Kernel Text Segment the Kernel Data start. */ SMD->kernelDataStart = (Address)TextSize; /* Note: DataSize is rounded to page boundary during assignments... :-) */ SMD->kernelDataSize = DataSize; /* USER */ SMD->userCodeStart = (Address)UADDR_BASE; SMD->userCodeSize = PAGEBOUNDARY(((BinFileDescPtr)ULOAD_ADDR)->codesize); SMD->userDataStart = (Address)((long)SMD->userCodeStart + (long)SMD->userCodeSize); SMD->userDataSize = PAGEBOUNDARY(((BinFileDescPtr)ULOAD_ADDR)->datasize); /* User Code starts in the appropriate segment right at location 40. */ SMD->userJumpAddress = NULL; if (userFound) SMD->userJumpAddress = (Address)UADDR_START; SMD->userLoadedInKernelAt = (Address)ULOAD_ADDR; } static void ShowTopsyi386() { char *lTopsy ="Topsy i386 v1.0, Lukas Ruf "; Printstr(24,(40-strlen(lTopsy)/2),0x1F,lTopsy); return; } void main() { TextSize = PAGEBOUNDARY(__getTextSize()); DataSize = PAGEBOUNDARY(__getDataSize()); VideoInit(); ShowTopsyi386(); /* I would like to show my name :-) */ /* GDTInit() must come first */ GDTInit(); /* Global Descriptor Table Initialization */ /* IDTInit() must come second */ IDTInit(); /* Interrupt Descriptor Table Initialization */ TSSInit(); /* Kernel Task State Selector */ ExceptionInit(); /* Processor Exception Handling */ MemoryInit(); /* Low Level Memory Management */ InterruptInit(); /* Peripheral Interrupt Handling */ TimerInit(); /* Enable Working Interrupts 0x00 Timer 0 */ BuildSegMap(); /* Create this SegMap Table */ segmap = &SegMapDesc_i386; /* initalize the segmap PTR */ ClearScreen(); bootStackBottom = BOOTSTACKBOTTOM; topsyMain(); }