home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol1 / bootexpcon / kickauto1.3 < prev    next >
Text File  |  1990-01-26  |  25KB  |  531 lines

  1. (c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice, and 
  3. is provided "as is" without warranty of any kind, either expressed or implied.  
  4. The entire risk as to the use of this information is assumed by the user.
  5.  
  6.  
  7.  
  8.                     V1.3 KICKSTART AND AUTOBOOT
  9.  
  10.                        by Bart Whitbrook
  11.  
  12.  
  13.        The V1.3 Kickstart allows devices other than DF0: to serve as the
  14.    Amiga system boot device.  The purpose of this article is to show how
  15.    you  may implement your own autoboot device in a system-compatible
  16.    fashion.
  17.  
  18.  
  19.    Features
  20.  
  21.        Kickstart V1.3 is an incremental kickstart release.  It is designed
  22.    to maintain V1.2 compatability throughout, while adding autoboot from
  23.    ROM-based expansion devices to the operating system.
  24.  
  25.        Automatic boot from any ROM-equipped expansion board is accomplished
  26.    at cold-start time, before the DOS exists.  This facility makes it
  27.    possible to automatically boot from a hard disk without any floppy
  28.    disks inserted.  Likewise, it is possible to automatically boot from any
  29.    device which supports the ROM protocol, such as nfs: over ethernet.
  30.  
  31.        Autoboot is implemented with the addition of the "romboot.library"
  32.    to the ROM resident list, as well as conservative changes to the
  33.    expansion.library, the dos.library and the strap.library.  These
  34.    changes have been carefully considered to be compatible with V1.2
  35.    (release 33.180) so that developers should not have to recompile
  36.    their code for software compatability.  Without autoboot hardware,
  37.    the V1.3 system will behave the same as the V1.2 release.
  38.  
  39.        Romboot.library functions are private at this time and are not
  40.    needed by those developing autoboot expansion devices or drivers for
  41.    such devices.
  42.        
  43.        
  44.  
  45.  
  46.  
  47. Changes Since V1.2 Release (33.180)
  48. -----------------------------------
  49.  
  50.    Seven kickstart modules have changed since the release of KS_33.180:
  51.  
  52.      1)  expansion34.1   --  functional change (internal only)
  53.      2)  graphics34.1    --  size change (no functional changes)
  54.      3)  strap34.1       --  functional change (internal only)
  55.      4)  romboot34.1     --  new module added to support autoboot
  56.      5)  wb34.1          --  size change (no functional changes)
  57.      6)  dos34.1         --  functional change (internal only)
  58.      7)  intuition34.1   --  functional change (extended preferences only)
  59.  
  60.    Six include files have changed since the release of KS_33.180:
  61.  
  62.      8)  exec/nodes.h               -- a new define added
  63.      9)  exec/node.i                -- a new define added
  64.      10) libraries/expansionbase.h  -- now public
  65.      11) libraries/expansionbase.i  -- now public
  66.      12) libraries/romboot_base.h   -- a newly created include file
  67.      13) libraries/romboot_base.i   -- a newly created include file
  68.      14) intuition/intuition.h      -- split off preferences.h and screens.h
  69.      15) intuition/intuition.i      -- split off preferences.i and screens.i
  70.      16) intuition/screen.h         -- new include (was part of intuition.h)
  71.      17) intuition/screen.i         -- new include (was part of intuition.i)
  72.      18) intuition/preferences.h    -- new include (was part of intuition.h)
  73.      19) intuition/preferences.i    -- new include (was part of intuition.i)
  74.  
  75.    Two library files have changed since the release of KS_33.180
  76.  
  77.      20) amiga.lib   -- addition of romboot.library
  78.      21) rom.lib     -- addition of romboot.library
  79.  
  80.  
  81.  
  82. How Auto Boot Works
  83. -------------------
  84.  
  85.        At system reboot time, and after exec is initialized, the expansion
  86.    initialization procedure is called.  As each expansion board in the
  87.    system is configured, the expansion initialization routine checks to see
  88.    whether this board has a valid ROM area associated with it.  If such a
  89.    ROM exists, its image is then copied into RAM memory.  This ROM "image"
  90.    contains rom/diagnostic routines, a driver associated with this expansion
  91.    board, and the board's bootstrap routine to actually boot the appropriate
  92.    operating system (normally, AmigaDOS).
  93.  
  94.        Once the ROM image is copied into RAM, the config routine calls
  95.    the rom/diagnostic vector of the board to perform any patching and/or
  96.    relocation of the ROM image to reflect its new location in RAM.  This
  97.    whole process is repeated for each auto-config board in the system.
  98.  
  99.        After the config routine, the other Resident Modules, except strap,
  100.    are initialized (graphics, intuition, etc.).  Now, a new V1.3 module,
  101.    romboot, is called upon to create the romboot.library.
  102.  
  103.        During its initialization phase, the romboot.library searches
  104.    through the ROM "images" for valid romtags.  When a valid romtag is
  105.    found, its rt_Init() function is called, to start up the driver
  106.    associated with this board.  If the driver is able to startup
  107.    successfully, the driver will enqueue a node on the expansion.library's
  108.    eb_MountList (see libraries/expansionbase.h).
  109.  
  110.        Finally, the Resident Module strap is initialized.  Strap first
  111.    checks to see if there is a valid boot disk in the internal drive, DF0:.
  112.    If there is, strap overrides the autoboot and boots from DF0: instead.
  113.  
  114.        If there is no valid boot disk in DF0:, strap will try to autoboot
  115.    by calling the romboot.library routine RomBoot().  For each appropriate
  116.    node on the eb_Mountlist, RomBoot() will locate and execute the
  117.    bootstrap routine for the board located in the associated ROM "image".
  118.    If the board's bootstrap routine is successful, the system will come up
  119.    using the board as the default boot device.
  120.  
  121.        If the autoboot fails, or if there are no appropriate nodes on the
  122.    eb_MountList, strap will ask for the user to insert a valid Workbench
  123.    disk, and will loop until its request is satisfied.
  124.  
  125.  
  126.  
  127. The Details of Autoboot
  128. -----------------------
  129.  
  130.    AT EXPANSION CONFIGURATION TIME:
  131.  
  132.        As part of its initialization, the expansion.library auto-configs
  133.    all the appropriate hardware boards in the system.
  134.  
  135.        When your auto-config hardware board is configured by the expansion
  136.    initialization routine, its ExpansionRom structure is copied into the
  137.    ExpansionRom subfield of a ConfigDev structure (see figure 1).  This
  138.    ConfigDev structure will be linked to the expansion.library as part
  139.    of the eb_BoardList.
  140.  
  141.         AFTER the board is configured, the er_Type field of its ExpansionRom
  142.    structure is checked (see figure 2).  The DIAGVALID bit set declares
  143.    that there is a valid DiagArea (you know, a rom/diagnostic area) on this
  144.    board.
  145.  
  146.        If there is a valid DiagArea, expansion next tests the er_InitDiagVec
  147.    vector in its copy of the ExpansionRom structure.  This offset is added
  148.    to the base address of the configured board; the resulting address points
  149.    to the start of this board's DiagArea.  Now expansion knows that there is
  150.    a DiagArea and where it is.
  151.  
  152.        Next, expansion tests the first byte (see figure 3) of the DiagArea
  153.    structure to determine if the CONFIGTIME bit is set.  If this bit
  154.    is set, it checks the da_BootPoint offset vector to make sure that a
  155.    valid bootstrap routine exists.  If so, expansion copies da_Size bytes
  156.    into RAM memory, beginning at DiagArea and continuing until the entire
  157.    DiagArea is copied into memory.
  158.  
  159.        The copy will start with the DiagArea structure itself, and typically
  160.    include a rom/diagnostic routine, a device driver, and the board's
  161.    bootstrap routine.  The copy will be made either nibblewise, bytewise,
  162.    or wordwise, according to the BUSWIDTH subfield of da_Config (see
  163.    figure 4).  Note that the da_BootPoint offset MUST BE NON-NULL, OR ELSE
  164.    NO COPY WILL OCCUR.
  165.  
  166.        Now the ROM "image" exists in RAM memory.  Expansion stores the
  167.    ULONG address of that "image" in the UBYTES er_Reserved0c, 0d, 0e and 0f.
  168.    The address is stored with the most significant byte in er_Reserved0c,
  169.    the next to most significant byte in er_Reserved0d, the next to least 
  170.    significant byte in er_Reserved0e, and the least significant byte
  171.    in er_Reserved0f (see figure 5).
  172.  
  173.        Expansion finally checks the da_DiagPoint offset vector, and if valid
  174.    executes the rom/diagnostic routine contained as part of the ROM "image".
  175.    This diagnostic routine is responsible for "patching" the ROM image so
  176.    that required absolute addresses are relocated to reflect the actual
  177.    location of the code, as well as performing any diagnostic functions 
  178.    essential to the operation of its associated auto-config board (see
  179.    figure 6).
  180.  
  181.        Your rom/diagnostic routine should return a non-zero value to
  182.    indicate success;  otherwise the ROM "image" will be unloaded from
  183.    memory, and its address will be replaced with NULL bytes in locations
  184.    er_Reserved0c, 0d, 0e and 0f.
  185.        
  186.        Now that the ROM "image" has been copied into RAM, validated, and
  187.    linked to board's ConfigDev structure, the expansion module is free to
  188.    configure all other boards on the eb_BoardList.
  189.  
  190.  
  191.    NEXT, OTHER RESIDENT MODULES ARE INITIALIZED:
  192.  
  193.        Currently, all Resident Modules (excepting strap) have a priority of
  194.    zero or above.  The new romboot Resident Module has a priority level of
  195.    -40.  The strap module has priority -60.  This means that Romboot will
  196.    be initialized after all other modules but before the (boot)strap module.
  197.  
  198.  
  199.    NOW, THE ROMBOOT.LIBRARY IS INITIALIZED:
  200.  
  201.        As part of the initialization procedure for the romboot.library,
  202.    a search is made of the expansion eb_BoardList (which contains a
  203.    ConfigDev structure for each of the auto-config hardware boards). 
  204.    If the cd_Flags specify CONFIGME and the er_Type specifies DIAGVALID,
  205.    the romboot device will do three things:
  206.  
  207.        First, it will bind the address of the current ConfigDev to the
  208.    eb_CurrentBinding structure (see expansion.library/SetCurrentBinding).
  209.  
  210.        Second, it will check the DiagArea's da_Config flag to make sure that
  211.    the CONFIGTIME bit is set.
  212.  
  213.        Third, it will search the ROM "image" associated with this hardware
  214.    board for a valid Resident structure (exec/resident.h); and, if one is
  215.    located, will call InitResident() on it, passing a NULL segment list
  216.    pointer as part of the call.
  217.  
  218.  
  219.    NOW, THIS BOARD'S DEVICE DRIVER IS INITIALIZED:
  220.  
  221.        The Resident structure associated with this board's device driver
  222.    (which has now been "patched" by the rom/diagnostic routine) should
  223.    follow standard system conventions in initializing the device driver
  224.    provided in the bootroms.  This driver should obtain the address of its
  225.    associated ConfigDev structure via the expansion eb_CurrentBinding
  226.    structure (see figure 7).
  227.  
  228.        Once the driver is initialized, it is responsible for some further
  229.    steps.  One, it must clear the CONFIGME bit in the cd_Flags of its
  230.    ConfigDev structure , so that the system knows not to configure this
  231.    device again if binddrivers is run after bootstrap.  Two, for this
  232.    device to be bootable, the driver must create a BootNode structure,
  233.    and link this BootNode onto the expansion eb_MountList.
  234.  
  235.    The BootNode structure (see libraries/romboot_base.h) contains a Node of
  236.    the "new" type NT_BOOTNODE (see exec/nodes.h). The driver MUST initialize
  237.    the bn_DeviceNode field to point to the ConfigDev structure which it has
  238.    obtained via the GetCurrentBinding() call.  The bn_Flags subfield
  239.    is currently unused and should be initialized to NULL.
  240.  
  241.        When the DOS is initialized later, it will attempt to boot from
  242.    the first BootNode on the eb_MountList.  The eb_MountList is a priority
  243.    sorted List, with nodes of the highest priority a the head of the List.
  244.    For this reason, the device driver must Enqueue() a BootNode onto the
  245.    List using the exec.library/Enqueue.
  246.  
  247.        In the case of an autoboot of AmigaDOS, the BootNode must be linked
  248.    to a DeviceNode of the AmigaDOS type (see libraries/filehandler.h), which
  249.    the driver can create via the expansion.library/MakeDosNode call.
  250.    When the DOS "wakes up",it will attempt to boot from this DeviceNode. 
  251.  
  252.    Note:   DOS, in this context, means "device operating system".
  253.            Typically this means AmigaDOS, although there is nothing
  254.            to prevent a system boot from another OS (UNIX, MS-DOS.
  255.            <boot via nfs:>, ETC.).
  256.  
  257.        When the romboot.library is finished setting up all the rom "images"
  258.    of all the boards in the system, the Resident Module strap takes over.
  259.  
  260.  
  261.   EXECUTION PASSES TO STRAP:
  262.  
  263.        This is where all your hard work pays off.
  264.  
  265.        If there is NO boot disk in the internal floppy drive, strap will
  266.    call the function romboot.library/RomBoot().  This routine performs the
  267.    autoboot. It will examine the eb_MountList; find the highest priority
  268.    BootNode structure at the head of the List; validate the BootNode; 
  269.    determine which ConfigDev on the eb_BootList is associated with this
  270.    BootNode; find its DiagArea; and call its da_BootPoint function in the
  271.    ROM "image" to bootstrap the appropriate DOS. This call, if successful,
  272.    should not return.
  273.    
  274.        Otherwise, if a boot disk IS in the internal floppy drive, the strap
  275.    will Enqueue() a BootNode on the eb_MountList for DF0: at the "suggested"
  276.    priority (see autodoc for expansion.library/AddDosNode).  Strap will then
  277.    open AmigaDOS, overriding the autoboot.  AmigaDOS will boot from the
  278.    highest priority node on the eb_MountList which should, in this case, be
  279.    DF0:.  Thus, games and other "bootable" floppy disks will still be able
  280.    to obtain the system for their own use.
  281.  
  282.        In the event that there is NO boot disk in the internal floppy drive
  283.    AND there are no ROM bootable devices on the auto-configuration chain,
  284.    the system does the normal thing, asking the user to insert a WorkBench
  285.    disk, and waiting until its request is satisfied before proceeding.
  286.  
  287.  
  288.        
  289.  
  290.  
  291. ------------------------------------------------------------------------
  292.                 Figure 1: the ConfigDev structure
  293. ------------------------------------------------------------------------
  294.  
  295.         struct ConfigDev 
  296.         {
  297.             struct Node         cd_Node;
  298.             UBYTE               cd_Flags;
  299.             UBYTE               cd_Pad;
  300.             struct ExpansionRom cd_Rom;         /* image of ExpansionRom  */
  301.             APTR                cd_BoardAddr;   /* for this ConfigDevice */
  302.             APTR                cd_BoardSize;   
  303.             UWORD               cd_SlotAddr;
  304.             UWORD               cd_SlotSize;
  305.             APTR                cd_Driver;
  306.             struct ConfigDev   *cd_NextCD;  
  307.             ULONG               cd_Unused[4];
  308.         };
  309.  
  310. ------------------------------------------------------------------------
  311.                 Figure 2: the ExpansionRom structure
  312. ------------------------------------------------------------------------
  313.  
  314.         struct ExpansionRom 
  315.         {
  316.             UBYTE   er_Type;            /* <-- if ERTB_DIAGVALID set */
  317.             UBYTE   er_Product;
  318.             UBYTE   er_Flags;
  319.             UBYTE   er_Reserved03;
  320.             UWORD   er_Manufacturer;
  321.             ULONG   er_SerialNumber;
  322.             UWORD   er_InitDiagVec;     /* <-- then er_InitDiagVec      */
  323.             UBYTE   er_Reserved0c;      /*     is added to cd_BoardAddr */
  324.             UBYTE   er_Reserved0d;      /*     and points to DiagArea   */
  325.             UBYTE   er_Reserved0e;      /*     ( see figure 3 )         */
  326.             UBYTE   er_Reserved0f;
  327.         };
  328.  
  329.  
  330. ------------------------------------------------------------------------
  331.                 Figure 3: the DiagArea structure
  332. ------------------------------------------------------------------------
  333.  
  334.         struct DiagArea 
  335.         {
  336.             UBYTE   da_Config;          /* <-- if DAC_CONFIGTIME is set */
  337.             UBYTE   da_Flags;
  338.             UWORD   da_Size;            /* <-- then da_Size bytes will  */
  339.             UWORD   da_DiagPoint;       /*     be copied into RAM       */
  340.             UWORD   da_BootPoint;       /*     ( see figure 4 )         */
  341.             UWORD   da_Name;    
  342.             UWORD   da_Reserved01;  
  343.             UWORD   da_Reserved02;
  344.         };
  345.  
  346.  
  347. ------------------------------------------------------------------------
  348.                 Figure 4: the RAM copy of the DiagArea structure
  349. ------------------------------------------------------------------------
  350.  
  351.                         DiagArea:  copy in RAM
  352.                            ( see figure 5 )
  353.  
  354.         +-> CCFF    ; da_Config, da_Flags <-----+ <-----+ <-----+
  355.         |   SIZE    ; da_Size                   |       |       |
  356.         S   DIAG    ; da_DiagPoint              N       B       D
  357.         I   BOOT    ; da_BootPoint              A       O       I
  358.         Z   NAME    ; da_Name                   M       O       A
  359.         E   0000    ; da_Reserved01             E       T       G
  360.         |   0000    ; da_Reserved02             |       |       |
  361.         |                                       |       |       |
  362.         |   nnnn    ; DiagArea + da_Name <+-----+       |       |
  363.         |   nnnn    ; name                              |       |
  364.         |   nnnn    ; name                              |       |
  365.         |   nnnn    ; name                              |       |
  366.         |   nnnn    ; name                              |       |
  367.         |                                               |       |
  368.         |   bbbb    ; DiagArea + da_bootPoint <---------+       |
  369.         |   bbbb    ; boot                                      |
  370.         |   bbbb    ; boot                                      |
  371.         |   bbbb    ; boot                                      |
  372.         |   bbbb    ; boot                                      |
  373.         |   bbbb    ; boot                                      |
  374.         |   bbbb    ; boot                                      |
  375.         |   bbbb    ; boot                                      |
  376.         |                                                       |
  377.         |   dddd    ; DiagArea + da_DiagPoint <-----------------+
  378.         |   dddd    ; diag
  379.         |   dddd    ; diag
  380.         |   dddd    ; diag
  381.         |   dddd    ; diag
  382.         |   dddd    ; diag
  383.         |   dddd    ; diag
  384.         |   dddd    ; diag 
  385.         |                   
  386.         +-> last    ; DiagArea + da_Size
  387.  
  388.  
  389. ------------------------------------------------------------------------
  390.                 Figure 5: where the pointer to the RAM copy is kept
  391. ------------------------------------------------------------------------
  392.  
  393.         struct ConfigDev 
  394.         {
  395.             struct Node cd_Node;
  396.             UBYTE       cd_Flags;
  397.             UBYTE       cd_Pad;
  398.             struct ExpansionRom {
  399.                 UBYTE   er_Type;
  400.                 UBYTE   er_Product;
  401.                 UBYTE   er_Flags;
  402.                 UBYTE   er_Reserved03;
  403.                 UWORD   er_Manufacturer;
  404.                 ULONG   er_SerialNumber;
  405.                 UWORD   er_InitDiagVec;
  406.                 UBYTE   er_Reserved0c;      /*  <-- address of RAM copy of  */
  407.                 UBYTE   er_Reserved0d;      /*      DiagArea is stored by   */
  408.                 UBYTE   er_Reserved0e;      /*      expansion.library in    */
  409.                 UBYTE   er_Reserved0f;      /*      these four bytes in the */
  410.             } cd_Rom;                       /*      image of ExpansionRom   */
  411.             APTR    cd_BoardAddr;           /*      for this ConfigDevice   */
  412.             APTR    cd_BoardSize;   
  413.             UWORD   cd_SlotAddr;
  414.             UWORD   cd_SlotSize;
  415.             APTR    cd_Driver;
  416.             struct ConfigDev   *cd_NextCD;  
  417.             ULONG   cd_Unused[4];
  418.         }; 
  419.  
  420.  
  421. ------------------------------------------------------------------------
  422.                 Figure 6: DiagArea Initialization and Relocation
  423. ------------------------------------------------------------------------
  424.  
  425.                 ( this figure omits several important steps )
  426.                 ( involved in error checking and relocation )
  427.                 ( of variables in the resident structure!!! )
  428.                 ( in this example the Init routine will be  )
  429.                 ( executed directly from the wordwide ROMS  )
  430.             
  431.     DiagArea:   dc.b    (DAC_WORDWIDE+DAC_CONFIGTIME)
  432.                 dc.b    (NULL)
  433.                 dc.w    (End-DiagArea)
  434.                 dc.w    (DiagPoint-DiagArea)
  435.                 dc.w    (BootPoint-DiagArea)
  436.                 dc.w    (Name-DiagArea)
  437.                 dc.w    (NULL)
  438.                 dc.w    (NULL)
  439.                                 
  440.     Resident:   dc.w    RTC_MATCHWORD   ; UWORD RT_MATCHWORD
  441.     rt_Match:   dc.l    Resident        ; APTR  RT_MATCHTAG
  442.     rt_End:     dc.l    End             ; APTR  RT_ENDSKIP
  443.                 dc.b    RTW_COLDSTART   ; UBYTE RT_FLAGS
  444.                 dc.b    VERSION         ; UBYTE RT_VERSION
  445.                 dc.b    NT_DEVICE       ; UBYTE RT_TYPE
  446.                 dc.b    20              ; BYTE  RT_PRI
  447.     rt_Name:    dc.l    Name            ; APTR  RT_NAME
  448.     rt_ID:      dc.l    Name            ; APTR  RT_IDSTRING
  449.     rt_Init:    dc.l    Init            ; APTR  RT_INIT == offset from ROM base
  450.     
  451.     Name:       dc.b    'AutoBoot',0    ; our own Name string
  452.  
  453.     DosName:    DOSNAME                 ; macro definition of DOS library name
  454.                 ds.w        0           ; word align code
  455.     
  456.     BootPoint:  lea DosName(PC),A1  
  457.                 jsr     _LVOFindResident(A6)    ; find the DOS resident tag
  458.                 move.l  d0,a0                   ; in order to bootstrap
  459.                 move.l  RT_INIT(A0),A0          ; set vector to DOS INIT
  460.                 jsr     (a0)                    ; and initialize DOS
  461.                 rts
  462.     
  463.     DiagPoint:  movem.l a1,-(sp)        ; a0 == pointer to boardbase
  464.                 lea     rt_Init(pc),a1  ; relocate address of Init routine
  465.                 move.l  (a1),d0         ; get long offset from ROM origin
  466.                 add.l   a0,d0           ; add the boardbase to the offset
  467.                 move.l  d0,(a1)         ; and replace offset with absolute
  468.                 movem.l (sp)+,a1        ; restore scratch register
  469.                 moveq.l #1,d0           ; indicate "success"
  470.                 rts
  471.  
  472.     End:        end
  473.  
  474.  
  475. ------------------------------------------------------------------------
  476.                 Figure 7: Adding a DOS BootNode to the eb_MountList 
  477. ------------------------------------------------------------------------
  478.  
  479.     char execName[] =   "trackdisk.device";  char dosName[] =   "DF1";
  480.     ULONG parmPkt[] =   /* a 3.5" amiga format floppy drive */ 
  481.     {   (ULONG) dosName,    
  482.         (ULONG) execName,
  483.         1,                  /* unit number */ 
  484.         0,                  /* OpenDevice flags */
  485.         12,                 /* table upper bound */
  486.         512>>2,             /* # longwords in a block */
  487.         0,                  /* sector origin */
  488.         2,                  /* number of surfaces */
  489.         1,                  /* secs per logical block */
  490.         11,                 /* secs per track */
  491.         2,                  /* reserved blocks -- 2 boot blocks */
  492.         0,                  /* unused */
  493.         0,                  /* interleave */
  494.         0,                  /* lower cylinder */
  495.         79,                 /* upper cylinder */
  496.         5,                  /* number of buffers */
  497.         3                   /* type of memory */    };
  498.  
  499.     Init() 
  500.     {
  501.         struct ExpansionBase *eb = OpenLibrary("expansion.library",V1_POINT_3);
  502.  
  503.         if(eb) 
  504.         { 
  505.             struct BootNode *bn = 
  506.             AllocMem(sizeof(struct BootNode),MEMF_PUBLIC|MEMF_CLEAR);
  507.  
  508.             if(bn) 
  509.             { 
  510.                 struct DeviceNode *dosnode = MakeDosNode( parmPkt );
  511.  
  512.                 if(dosnode) 
  513.                 { 
  514.                     struct CurrentBinding curbind;
  515.  
  516.                     GetCurrentBinding(&curbind, sizeof(struct CurrentBinding));
  517.                     bn->bn_Node.ln_Type = NT_BOOTNODE;          
  518.                     bn->bn_Node.ln_Pri  = 5;            
  519.                     bn->bn_Node.ln_Name = curbind.cb_ConfigDev;         
  520.                     bn->bn_Flags        = NULL;
  521.                     bn->bn_DeviceNode   = dosnode;
  522.  
  523.                     Enqueue(&eb->MountList,bn);
  524.                     
  525.                 } else { FreeMem(bn,sizeof(struct BootNode)); }
  526.             }
  527.         }
  528.     }
  529.  
  530.  
  531.