Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  * Mini-loader for the SVGM BSP.
0003  *
0004  * Author: Till Straumann, 10/2001 <strauman@slac.stanford.edu>
0005  *
0006  * Some ideas are borrowed from the powerpc/shared/bootloader
0007  * by
0008  *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
0009  *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
0010  *
0011  * The SMON firmware is unable to load the RTEMS image below
0012  * 0x2000 (I believe their stack is growing below 0x1000).
0013  *
0014  * The code provided by this file is responsible for the performing
0015  * the following steps:
0016  *
0017  *  1) Save commandline parameters to an area that is
0018  *       a) not covered by the downloaded image
0019  *       b) will not be overwritten by the moved image
0020  *          nor the final BSS segment (rtems clears BSS
0021  *          before saving the command line).
0022  *  2) Move the entire image (including this very file) to
0023  *     its final location starting at 0x0000.
0024  *     It is important to note that _NO_STACK_ is available
0025  *     during this step. Also, there is probably no return to
0026  *     SMON because relocating RTEMS will destroy vital SMON
0027  *     data (such as its stack).
0028  *  3) Flush the cache to make sure the relocated image is actually
0029  *     in memory.
0030  *  4) setup RTEMS environment (initial register values), most
0031  *     notably an initial STACK. The initial stack may be small and
0032  *     is used by RTEMS only at a very early stage.
0033  *     A safe place for the stack seems to be the 00..0x7f area.
0034  *     NOTE: we should respect the MAILBOX area 0x80..0xff!
0035  *  5) switch the MMU off (because that's what RTEMS is expecting
0036  *     it to be at startup).
0037  *  6) fire up rtems...
0038  *
0039  *
0040  *  Calling convention:
0041  *     R1: SMON SP
0042  *     R3: command line string start
0043  *     R4: command line string end + 1
0044  *     R5: where SMON put the image
0045  *         if R5 is 0, the preloader will use its entry point
0046  *         as the image starting address.
0047  *         See NOTE below.
0048  *     R6: end of the image (i.e. R6-R5 is the image length)
0049  *         if R6 is 0, _edata will be used as the image length
0050  *         See NOTE below.
0051  *
0052  *     NOTE: if the symbol DONT_USE_R5_ENTRY is defined,
0053  *         R5/R6 are never used and the necessary parameters are
0054  *         determined at runtime (R5) / linkage (R6) [_edata]
0055  *
0056  *  ASSUMPTIONS:
0057  *    The code RELIES on the assumption that the image will be
0058  *    moved DOWNWARDS in memory and that the this loader is
0059  *    prepended to the image, i.e. it is safe to do
0060  *        codemove(codemove,0,codemove_end - codemove);
0061  *        (*0)(codemove_end, codemove_end-codemove, __rtems_end-codemove_end);
0062  *    where codemove(from, to, nbytes) is defined as
0063  *        codemove(from, to, nbytes) { while (nbytes--) *(to++)=*(from++); }
0064  *    Implicit to these assumptions is the assumption that the destination
0065  *    address is cache block aligned.
0066  *    Furthermore, the byte count is assumed to be a multiple
0067  *    of four
0068  *
0069  */
0070 #if 0
0071 #include <rtems/score/powerpc.h>
0072 #else
0073 #ifndef PPC_CACHE_ALIGNMENT
0074 #define PPC_CACHE_ALIGNMENT 32
0075 #endif
0076 #endif
0077 
0078 #include <rtems/score/cpu.h>
0079 #include <rtems/asm.h>
0080 
0081 /* Note that major modifications may be needed
0082  * if DESTINATION_ADDR is not 0
0083  */
0084 #define KERNELBASE          0x0
0085 #define INITIAL_STACK       0x70                    /* 16-byte aligned */
0086 #define CACHE_LINE_SIZE     PPC_CACHE_ALIGNMENT     /* autodetect doesn't work, see below */
0087 #define ASSUME_RTEMS_INSTALLS_VECTORS               /* assume we need not load vectors */
0088 #define DONT_USE_R5_ENTRY                           /* always dynamically determine the address we're running from */
0089 
0090     /* put this into its own section which we want to
0091      * be loaded at the very beginning. We should probably
0092      * not use more than 255 bytes.
0093      */
0094     PUBLIC_VAR(__rtems_start)
0095     PUBLIC_VAR(__rtems_entry_point)
0096     PUBLIC_VAR(__rtems_end)
0097     .section .entry_point_section,"awx",@progbits
0098 preload:
0099     /* find out where we are */
0100     bl  here
0101 here:
0102     xor     r0,r0,r0
0103     mtmsr   r0  /* clear MSR to known state */
0104     mflr    r5
0105     addi    r5,r5,-(here-preload)
0106     lis     r27,_edata@h
0107     ori     r27,r27,_edata@l
0108 
0109     /* at this point the register contents are
0110      * R3:  command line start
0111      * R4:  R3 + command line length
0112      * R5:  address we are running from / loaded to
0113      * R27: image end
0114      */
0115 
0116     /* save command line start */
0117     mr      r6, r3
0118     /* save the command line parameters if they are to be overwritten */
0119     sub.    r17, r4, r3     /* string length */
0120     ble     leaveparms      /* <=0 -> no parameters */
0121     /* copy has to be out of the way of the bss; therefore we must
0122      * put the string out of the way of both, the current end of
0123      * the image (without bss) AND the end of the loaded image
0124      * (including bss):
0125      * |......image.........|  downloaded image
0126      * |image_bss...........|  loaded image with bss appended
0127      *
0128      *             ^ safe place for string
0129      *
0130      * the alternative scenario looks like this:
0131      * |..image.............|  downloaded image
0132      * |image_bss...........|  loaded image with bss appended
0133      *           ^ safe place for string
0134      */
0135     lis     r18, __rtems_end+0x10000@h  /* round up, save one instruction */
0136     add     r16, r5, r27    /* image end + 1 */
0137     cmpw    r16, r18
0138     bge     ishighenough
0139     mr      r16,r18         /* __rtems_end is higher than the image end
0140                              * (without bss)
0141                              */
0142 ishighenough:
0143     cmpw    r16, r3         /* destination start > current string start ? */
0144     ble     leaveparms      /* string already after dst, leave it */
0145     /* copy string from the last byte downwards */
0146     add     r6, r16, r17    /* last byte of destination + 1 */
0147     mtctr   r17
0148 1:
0149     lbzu    r3, -1(r4)
0150     stbu    r3, -1(r6)
0151     bdnz    1b
0152 leaveparms:
0153     add     r7, r6, r17     /* destination + strlen */
0154 
0155 #ifndef CACHE_LINE_SIZE
0156     /* Oh well, SMON has inhibited the cache, so this
0157      * nice routine doesn't work...
0158      */
0159     /* figure out the cache line size */
0160     li      r16, 0x80
0161     cmpw    r5, r16         /* 'from' must be > 0x80 */
0162     blt     panic
0163 
0164 1:  /* store some arbitrary, nonzero stuff in 0..0x7c */
0165     stwu    r16,-4(r16)
0166     cmpwi   r16,0
0167     bne     1b
0168     dcbz    0,r16           /* zero out one cache line */
0169     subi    r16,r16,4
0170 2:  lwzu    r0,4(r16)       /* search for a non-zero word */
0171     cmpwi   r0,0
0172     beq     2b
0173     /* OK, r16 now hold the size of a cache line in bytes */
0174 #else
0175     li      r16,CACHE_LINE_SIZE
0176 #endif
0177 
0178     lis     r3,preload@h
0179     ori     r3,r3,preload@l
0180     mr      r4,r5           /* from-addr */
0181     li      r5,_preload_size/* this is never > 16k */
0182     /* now move ourselves to the link address ('preload').
0183      * We set up the LR, so domove() 'returns' to the
0184      * relocated copy
0185      */
0186     lis     r0,return_here@h
0187     ori     r0,r0,return_here@l
0188     mtlr    r0
0189     b       domove          /* move the preloader itself */
0190 return_here:
0191     /* now we move the entire rest of the image */
0192 #ifdef ASSUME_RTEMS_INSTALLS_VECTORS
0193     lis     r3,__rtems_start@h
0194     ori     r3,r3,__rtems_start@l
0195     lis     r0,preload@h    /* calculate/adjust from address */
0196     ori     r0,r0,preload@l
0197     sub     r0,r3,r0
0198     add     r4,r4,r0
0199     sub     r5,r27,r3
0200 #else
0201     add     r3,r3,r5        /* add preloader size to destination */
0202     add     r4,r4,r5        /* and source addresses */
0203     sub     r5,r27,r5       /* length of the remaining rest */
0204 #endif
0205     bl      domove
0206     /* OK, now everything should be in place.
0207      * we are ready to start...
0208      */
0209 
0210     /* setup initial stack for rtems early boot */
0211     li      r1,INITIAL_STACK
0212     /* tag TOS with a NULL pointer (for stack trace) */
0213     li      r0, 0
0214     stw     r0, 0(r1)
0215     /* disable the MMU and fire up rtems */
0216     mfmsr   r0
0217     ori     r0,r0,MSR_IR|MSR_DR|MSR_IP|MSR_ME
0218     xori    r0,r0,MSR_IR|MSR_DR
0219     mtsrr1  r0
0220     lis     r0,__rtems_entry_point@h
0221     ori     r0,r0,__rtems_entry_point@l
0222     mtsrr0  r0
0223     /* R6: start of command line */
0224     /* R7: end of command line +1 */
0225     rfi
0226 
0227     /* domove(to, from, nbytes):
0228      *
0229      * move a R5 bytes from R4 to R3 and flush
0230      * the caches for the destination memory
0231      * region. R16 provides the cache line size.
0232      * DESTROYS: R0, R17, R18, CTR, CR
0233      */
0234 domove:
0235     addi    r0,r5,3         /* convert to word count */
0236     srwi.   r0,r0,2
0237     beq 3f                  /* nothing to do */
0238     cmpw    r3,r4           /* from == to ?  */
0239     beq 3f
0240     mtctr   r0
0241     la      r18,-4(r4)
0242     la      r17,-4(r3)
0243 1:  lwzu    r0,4(r18)
0244     stwu    r0,4(r17)
0245     bdnz    1b              /* move data */
0246     /* now, we must flush the destination cache region */
0247 #ifndef CACHE_LINE_SIZE
0248     cmpwi   r16,0
0249     beq     3f              /* nothing to do */
0250 #endif
0251 #if defined(CACHE_LINE_SIZE) && CACHE_LINE_SIZE > 0
0252     add     r17,r3,r5       /* target end pointer */
0253     subi    r0,r16,1
0254     add     r17,r17,r0
0255     andc    r17,r17,r0      /* cache aligned target end pointer */
0256     mr      r18,r3
0257 2:  cmpw    r18,r17
0258     dcbst   0,r18           /* write out data cache line */
0259     icbi    0,r18           /* invalidate corresponding i-cache line */
0260     add     r18,r18,r16
0261     blt     2b
0262     sync                    /* make sure data is written back */
0263     isync                   /* invalidate possibly preloaded instructions */
0264 #endif
0265 3:
0266     blr
0267 
0268 #if !defined(CACHE_LINE_SIZE)
0269 panic:
0270     li      r10,0x63
0271     mfmsr   r0
0272     ori     r0,r0,MSR_IP
0273     mtmsr   r0
0274     sc
0275 #endif
0276 
0277 /* DONT PUT ANY CODE BELOW HERE */
0278 _preload_size = . - preload