home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / config / amiga / boot / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-07  |  11.0 KB  |  491 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: main.c,v 1.9 1997/02/06 15:22:47 ldp Exp $
  4.  
  5.     Desc: Amiga bootloader -- main file
  6.     Lang: C
  7. */
  8.  
  9. /*
  10.     Note: This whole thing may seem a bit kludgy. It is. It was originally
  11.     designed to load only one module. It has been extended to read a config
  12.     file and to load multiple modules. It needs some polishing.
  13. */
  14.  
  15. #include <exec/types.h>
  16. #include <exec/execbase.h>
  17. #include <exec/nodes.h>
  18. #include <exec/resident.h>
  19. #include <exec/memory.h>
  20. #include <dos/dos.h>
  21.  
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24.  
  25. #include "boot.h"
  26. #include "ils.h"
  27. #include "config.h"
  28. #include "version.h"
  29.  
  30. #define D(x) if (debug) x
  31. #define bug Printf
  32. LONG Printf(STRPTR format, ...);
  33.  
  34. struct Module *LoadModule(char *);
  35. void FreeModules(struct ModuleList *);
  36. BOOL BuildTagPtrs(struct ModuleList *);
  37. struct MemList *BuildMemList(struct ilsMemList *, ULONG *, ULONG);
  38. void StuffTags(struct MemList *, ULONG *, ULONG);
  39. void *FindResMod(struct ilsMemList *);
  40. void PrintTagPtrs(void);
  41.  
  42. char *version = "$VER: " BANNER " " VERSIONSTRING " " DATE;
  43. char *configfile = "boot.config";
  44.  
  45. ULONG stack = 16384;
  46. ULONG memtype;
  47. BOOL debug;
  48. ULONG ils_table[3];
  49. struct ilsMemList ils_mem;
  50.  
  51. char usage[] =
  52. {
  53.     " -c -- force to chipmem\n"
  54.     " -f -- force to fastmem\n"
  55.     " -k -- force to kickmem\n"
  56.     " -d -- output debug information\n"
  57. };
  58.  
  59. int main(int argc, char **argv)
  60. {
  61.     struct FileList *filelist;
  62.     struct Node *node;
  63.     struct Module *module;
  64.     struct ModuleList ModuleList;
  65.     STRPTR modname;
  66.     int returnvalue = RETURN_OK;
  67.  
  68.     debug = FALSE;
  69.  
  70.     PutStr("\n" BANNER " " VERSIONSTRING "\n\n");
  71.  
  72.     if(SysBase->LibNode.lib_Version < 37)
  73.     {
  74.     PutStr("This utility is for AmigaOS 2.04 (V37) and higher\n\n");
  75.     exit(RETURN_WARN);
  76.     }
  77.  
  78.     /*
  79.     The memory type MEMF_KICK has been added in V39 exec. Fall back to
  80.     MEMF_CHIP if we are on an earlier version.
  81.     */
  82.     if(SysBase->LibNode.lib_Version < 39)
  83.     {
  84.     memtype = MEMF_CHIP;
  85.     } else
  86.     {
  87.     memtype = MEMF_KICK;
  88.     }
  89.  
  90.     for (argc--, argv++; argc; argc--, argv++)
  91.     {
  92.     if (**argv != '-')
  93.     {
  94.         continue;
  95.     }
  96.     switch(argv[0][1])
  97.     {
  98.         case 'h':
  99.         PutStr(usage);
  100.         exit(RETURN_OK);
  101.         break;
  102.         case 'c':
  103.         memtype = MEMF_CHIP;
  104.         break;
  105.         case 'f':
  106.         memtype = MEMF_FAST;
  107.         break;
  108.         case 'k':
  109.         memtype = MEMF_KICK;
  110.         break;
  111.         case 'd':
  112.         debug = TRUE;
  113.     }
  114.     }
  115.  
  116.     D(bug("Debug mode\n"));
  117.  
  118.     PrintTagPtrs();
  119.  
  120.     /*
  121.     InternalLoadSeg use.
  122.     */
  123.     ils_table[0] = (ULONG)&ils_read;
  124.     ils_table[1] = (ULONG)&ils_alloc;
  125.     ils_table[2] = (ULONG)&ils_free;
  126.  
  127.     NewList((struct List *)&ils_mem);
  128.  
  129.     /*
  130.     Construct a List of filenames to process.
  131.     */
  132.     if(!(filelist = ReadConfig(configfile)))
  133.     {
  134.     PutStr("Error reading config file\n");
  135.     exit(RETURN_ERROR);
  136.     }
  137.  
  138.     PutStr("Loading modules ...\n");
  139.  
  140.     NewList((struct List *)&ModuleList);
  141.     ModuleList.ml_Num = 0;
  142.  
  143.     /*
  144.     Traverse this list and load the modules into memory.
  145.     */
  146.     for(node = filelist->fl_List.lh_Head; node->ln_Succ; node = node->ln_Succ)
  147.     {
  148.     modname = node->ln_Name;
  149.     if( (module = LoadModule(node->ln_Name)) )
  150.     {
  151.         AddTail((struct List *)&ModuleList, (struct Node *)module);
  152.         ModuleList.ml_Num++;
  153.         Printf("\t%s\n", (ULONG)module->m_Resident->rt_IdString);
  154.     }
  155.     else
  156.     {
  157.         node = 0; /* on normal exit, this points to the last module processed */
  158.         break;
  159.     }
  160.     }
  161.  
  162.     if(node)
  163.     {
  164.     /*
  165.         If we're here, all modules we're loaded normally. Build all
  166.         structures needed for the KickTag/Mem fields, and put them there.
  167.     */
  168.     if( (BuildTagPtrs(&ModuleList)) )
  169.     {
  170.         PutStr("\nAll modules loaded successfully, reset to activate.\n\n");
  171.     }
  172.     else
  173.     {
  174.         PutStr("\nError building KickTagPtrs!\n");
  175.         FreeModules(&ModuleList);
  176.         returnvalue = RETURN_FAIL;
  177.     }
  178.     }
  179.     else
  180.     {
  181.     Printf("Error loading \"%s\"\n", modname);
  182.     FreeModules(&ModuleList);
  183.     returnvalue = RETURN_FAIL;
  184.     }
  185.  
  186.     FreeConfig(filelist);
  187.  
  188.     exit(returnvalue);
  189. }
  190.  
  191. struct Module *LoadModule(char *filename)
  192. {
  193.     BPTR fh, seglist;
  194.     struct Module *mod;
  195.  
  196.     D(bug("LoadModule(\"%s\")\n", filename));
  197.     if(!(fh = Open(filename, MODE_OLDFILE)))
  198.     {
  199.     PrintFault(IoErr(), filename);
  200.     return 0;
  201.     }
  202.  
  203.     if(!(mod = AllocVec(sizeof(struct Module), MEMF_CLEAR)))
  204.     {
  205.     PutStr("Could not allocate memory for module.\n");
  206.     Close(fh);
  207.     return 0;
  208.     }
  209.     D(bug("  module   = 0x%08lx (size %ld)\n", mod, sizeof(struct Module)));
  210.  
  211.     if( (seglist = InternalLoadSeg(fh, NULL, &ils_table[0], &stack)) )
  212.     {
  213.     mod->m_SegList = seglist;
  214.     mod->m_Resident = FindResMod(&ils_mem);
  215.     }
  216.     Close(fh);
  217.     D(bug("  SegList  = 0x%08lx\n", BADDR(mod->m_SegList)));
  218.     D(bug("  Resident = 0x%08lx\n", mod->m_Resident));
  219.  
  220.     /*
  221.     If this module contains a Resident structure, return it.
  222.     */
  223.     if ( (mod->m_Resident))
  224.     {
  225.     return mod;
  226.     }
  227.  
  228.     return 0;
  229. }
  230.  
  231. void FreeModules(struct ModuleList *modlist)
  232. {
  233.     struct Module *mod, *next;
  234.  
  235.     D(bug("FreeModules(0x%08lx)\n", modlist));
  236.  
  237.     for(mod = (struct Module *)modlist->ml_List.mlh_Head; mod->m_Node.mln_Succ; mod = next)
  238.     {
  239.     /* get next node here, because after the Remove() it is undefined */
  240.     next = (struct Module *)mod->m_Node.mln_Succ;
  241.     Remove((struct Node *)mod);
  242.     InternalUnLoadSeg(mod->m_SegList, &ils_free);
  243.     FreeVec(mod);
  244.     }
  245. }
  246.  
  247. BOOL BuildTagPtrs(struct ModuleList *modlist)
  248. {
  249.     struct MemList *memlist;
  250.     ULONG *modarray;
  251.     ULONG i, nummods;
  252.     struct Module *mod;
  253.  
  254.     D(bug("BuildTagPtrs()\n"));
  255.  
  256.     /*
  257.     Allocate memory for our KickTagPtr table:
  258.     number of modules loaded + 1 (table terminator)
  259.     */
  260.     if( (modarray = AllocVec((modlist->ml_Num+1)*sizeof(ULONG),
  261.                  memtype|MEMF_CLEAR|MEMF_REVERSE)) )
  262.     {
  263.     /*
  264.         Fill the KickTagPtr array with pointers to our Resident modules.
  265.     */
  266.     for(i = 0, mod = (struct Module *)modlist->ml_List.mlh_Head;
  267.         mod->m_Node.mln_Succ;
  268.         mod = (struct Module *)mod->m_Node.mln_Succ, i++)
  269.     {
  270.         modarray[i] = (ULONG)mod->m_Resident;
  271.     }
  272.     /*
  273.         Terminate the module array.
  274.     */
  275.     modarray[i+1] = NULL;
  276.  
  277.     /*
  278.         Cache number of modules, since it will be modified in BuildMemList.
  279.     */
  280.     nummods = modlist->ml_Num;
  281.  
  282.     /*
  283.         build a memlist to be put in KickMemPtr
  284.     */
  285.     if( (memlist = BuildMemList(&ils_mem, modarray,
  286.                     (modlist->ml_Num+1)*sizeof(ULONG) )) )
  287.     {
  288.         StuffTags(memlist, modarray, nummods);
  289.         return TRUE;
  290.     }
  291.     FreeVec(modarray);
  292.     }
  293.     return FALSE;
  294. }
  295.  
  296. struct MemList *BuildMemList(struct ilsMemList *prelist,
  297.                  ULONG *        modlist,
  298.                  ULONG         modlistsize)
  299. {
  300.     struct MemList *memlist;
  301.     struct MemEntry *me;
  302.     struct ilsMemNode *node;
  303.     UWORD numentries;
  304.     ULONG size;
  305.  
  306.     D(bug("BuildMemList()\n"));
  307.     /*
  308.     Calculate needed number of extra MemEntry fields that need to be
  309.     appended to the end of our MemList structure. This number+1 (there
  310.     already is one MemEntry in the MemList) is what we'll be putting in
  311.     memlist->ml_NumEntries later.
  312.     */
  313.     numentries = prelist->iml_Num + 1;
  314.     D(bug(" number of modules = %ld\n", prelist->iml_Num));
  315.  
  316.     size = ( sizeof(struct MemList) + (sizeof(struct MemEntry) * numentries) );
  317.  
  318.     /*
  319.     Allocate memory from the top of the memory list, to keep fragmentation
  320.     down, and hopefully to keep all our applications in one place.
  321.     */
  322.     if(!(memlist = AllocVec(size, memtype|MEMF_CLEAR|MEMF_REVERSE))) return(NULL);
  323.  
  324.     /*
  325.     We have the memory. Assure that this MemList is allocated during a
  326.     reset, and put it in the first MemEntry field.
  327.     */
  328.     memlist->ml_ME[0].me_Addr = memlist;
  329.     memlist->ml_ME[0].me_Length = size;
  330.  
  331.     /*
  332.     Indicate that this node is part of a KickMem MemList, and indicate how
  333.     many MemEntries there are.
  334.     */
  335.     memlist->ml_Node.ln_Type = NT_KICKMEM;
  336.     memlist->ml_NumEntries = numentries+1;
  337.  
  338.     /*
  339.     Put the modlist in the next MemEntry.
  340.     */
  341.     me = (struct MemEntry *)( ((ULONG)memlist) + sizeof(struct MemList) );
  342.     me->me_Addr = modlist;
  343.     me->me_Length = modlistsize;
  344.  
  345.     /*
  346.     Increase to the next MemEntry.
  347.     */
  348.     me = (struct MemEntry *)( ((ULONG)me) + sizeof(struct MemEntry) );
  349.  
  350.     /*
  351.     Now put the data from our prelist in the remaining MemEntry fields,
  352.     removing the nodes in our prelist and freeing them in the process.
  353.     */
  354.     while(prelist->iml_Num)
  355.     {
  356.     /*
  357.         pop a node off the list
  358.     */
  359.     node = (struct ilsMemNode *)RemHead((struct List *)prelist);
  360.  
  361.     me->me_Addr = node->imn_Addr;
  362.     me->me_Length = node->imn_Size;
  363.  
  364.     FreeMem(node, sizeof(struct ilsMemNode));
  365.  
  366.     /*
  367.         Point to the next MemEntry, decrease our counter.
  368.     */
  369.     me = (struct MemEntry *)(((ULONG)me) + sizeof(struct MemEntry));
  370.     prelist->iml_Num--;
  371.     }
  372.  
  373.     return memlist;
  374. }
  375.  
  376. void StuffTags(struct MemList *memlist, ULONG *modlist, ULONG nummods)
  377. {
  378.     D(bug("StuffTags(memlist 0x%08lx  modlist 0x%08lx  nummods %ld)\n",
  379.      memlist, modlist, nummods));
  380.  
  381.     /* Fix 970102 ldp: protect the Kick ptrs with Forbid/Permit */
  382.     Forbid();
  383.  
  384.     if(SysBase->KickMemPtr)
  385.     {
  386.     /*
  387.         Prepend to an existing chain of MemLists.
  388.     */
  389.     memlist->ml_Node.ln_Succ = SysBase->KickMemPtr;
  390.     }
  391.     SysBase->KickMemPtr = memlist;
  392.  
  393.     if(SysBase->KickTagPtr)
  394.     {
  395.     /*
  396.         Prepend to an existing chain of module lists.
  397.     */
  398.     modlist[nummods] = (ULONG)SysBase->KickTagPtr | 0x80000000;
  399.     }
  400.     SysBase->KickTagPtr = modlist;
  401.  
  402.     /*
  403.     Flush caches. I have some problems with having to boot twice to get
  404.     into AROS. Maybe this will help? Or it may be the BlizKick util I'm
  405.     using that gets in the way? Or maybe something totally unexpected? :)
  406.  
  407.     Update: this didn't help. I still have to run boot twice to get AROSfA
  408.     loaded for the first time. If AROSfA is already loaded, I can just clear
  409.     the vectors and load boot again, and it will load correctly. Strange.
  410.     */
  411.     CacheClearU();
  412.  
  413.     /*
  414.     And checksum the KickPtrs. KickCheckSum is defined wrong in the include
  415.         file exec/execbase.h. It is defined as APTR, but really is a ULONG.
  416.     */
  417.     SysBase->KickCheckSum = (APTR)SumKickData();
  418.  
  419.     /*
  420.     Flush caches.
  421.     */
  422.     CacheClearU();
  423.  
  424.     Permit();
  425. }
  426.  
  427. void *FindResMod(struct ilsMemList *list)
  428. {
  429.     struct ilsMemNode *node;
  430.     UWORD *ptr;
  431.     ULONG num, counter;
  432.  
  433.     D(bug("FindResMod() ... "));
  434.  
  435.     /*
  436.     Search all memory blocks for the Resident struct. Only new nodes
  437.     will be searched.
  438.     */
  439.     for(node = (struct ilsMemNode *)ils_mem.iml_List.mlh_Head, num = ils_mem.iml_NewNum;
  440.     node->imn_Node.mln_Succ || num;
  441.     node = (struct ilsMemNode *)node->imn_Node.mln_Succ, num--)
  442.     {
  443.     /*
  444.         In each block: skip to the magic word, if present.
  445.         Searching by word: divide by 2
  446.     */
  447.     counter = node->imn_Size/2;
  448.  
  449.     for(ptr = node->imn_Addr; counter; ptr++, counter--)
  450.     {
  451.         if(RTC_MATCHWORD == *ptr)
  452.         {
  453.         /*
  454.             Reset the counter, so that next time only new nodes will
  455.             be searched.
  456.         */
  457.         ils_mem.iml_NewNum = 0;
  458.  
  459.         D(bug("found at 0x%08lx\n", ptr));
  460.         return((void *)ptr);
  461.         }
  462.     }
  463.     }
  464.  
  465.     D(bug("not found\n"));
  466.     return 0;
  467. }
  468.  
  469. void PrintTagPtrs(void)
  470. {
  471.     if(SysBase->KickTagPtr)
  472.     {
  473.     ULONG *list;
  474.  
  475.     PutStr("Modules already in use:\n");
  476.  
  477.     list = SysBase->KickTagPtr;
  478.  
  479.     while(*list)
  480.     {
  481.         Printf("\t0x%08lx", *list);
  482.         Printf("\t%s\n", (ULONG)((struct Resident *)*list)->rt_IdString);
  483.  
  484.         list++;
  485.         if(*list & 0x80000000) list = (ULONG *)(*list & 0x7fffffff);
  486.     }
  487.     }
  488. }
  489.  
  490. /* main.c */
  491.