source: trunk/tools/bootloader_tsar/boot.c @ 1

Last change on this file since 1 was 1, checked in by alain, 7 years ago

First import

File size: 34.1 KB
Line 
1/****************************************************************************
2 * This file contains the ALMOS-MKH. boot-loader for the TSAR architecture.  *
3 *                                                                          *
4 * It supports clusterised shared memory multi-processor architectures,     *
5 * where each processor is identified by a composite index [cxy,lid],       *
6 * with one physical memory bank per cluster.                               *
7 *                                                                          *
8 * The 'boot.elf' file (containing the boot-loader binary code) is stored   *
9 * on disk and is loaded into memory by bscpu (whose index is [0,0]),       *
10 * executing the generic preloader.                                         *
11 *                                                                          *
12 * 1) The boot-loader first phase is executed by bscpu only, while          *
13 *    all other cores are waiting in the preloader.                         *
14 *    It does the following tasks:                                          *
15 *      - load into the memory bank of cluster (0,0) the 'arch_info.bin'    *
16 *        file (containing the hardware architecture description) and the   *
17 *        'kernel.elf' file, at temporary locations,                        *   
18 *      - initializes the 'boot_info_t' structure in cluster(0,0)           *
19 *        (there is 1 'boot_info_t' per cluster), which contains both       *
20 *        global and cluster specific information that will be used for     *
21 *        kernel initialisation.                                            *
22 *      - activate CP0s in all other clusters, using IPIs.                  *
23 *      - wait completion reports from CP0s on a global barrier.            *
24 *                                                                          *
25 * 2) The boot-loader second phase is then executed in parallel by all      *
26 *    CP0s (other than bscpu). Each CP0 performs the following tasks:       *
27 *      - copies into the memory bank of the local cluster the 'boot.elf',  *
28 *        the 'arch_info.bin' (at the same addresses as the 'boot.elf' and  *
29 *        the 'arch_info.bin' in the memory bank of the cluster(0,0), and   *
30 *        the kernel image (at address 0x0),                                *
31 *      - initializes the 'boot_info_t' structure of the local cluster,     *
32 *      - activate all other cores in the same cluster (CPi).               *
33 *      - wait local CPi completion reports on a local barrier.             *
34 *      - report completion to bscpu on the global barrier.                 *
35 *                                                                          *
36 * 3) The boot-loader third phase is executed in parallel by all cores.     *
37 *    After passing the global barrier the bscpu:                           *
38 *      - activates the CPi of cluster(0,0),                                *
39 *      - blocks on the local barrier waiting for all local CPi to report   *
40 *        completion on the local barrier,                                  *
41 *      - moves the local kernel image from the temporary location to the   *
42 *        address 0x0, (erasing the preloader code).                        *
43 *                                                                          *
44 * 4) All cores have finished the boot phase, they jump to the kern_init()  *
45 *    function (maybe not at the same time).                                *
46 ****************************************************************************/
47
48#include <elf-types.h>
49
50#include <almos_config.h>
51#include <boot_config.h>
52
53#include <arch_info.h>
54#include <boot_info.h>
55
56#include <hal_types.h>
57
58#include <boot_utils.h>
59#include <boot_fat32.h>
60#include <boot_bdv_driver.h>
61#include <boot_hba_driver.h>
62#include <boot_tty_driver.h>
63
64/****************************************************************************
65 *                                 Macros.                                  *
66 ****************************************************************************/
67
68#define PAGE_ROUND_DOWN(x)  ((x) & (~PPM_PAGE_SIZE -1))
69#define PAGE_ROUND_UP(x)    (((x) + PPM_PAGE_SIZE-1) &   \
70                            (~(PPM_PAGE_SIZE-1)))
71
72/****************************************************************************
73 *                             Global variables.                            *
74 ****************************************************************************/
75
76// synchronization variables.
77volatile boot_barrier_t global_barrier;     /* Used by bscpu to synchronize
78                                               with other CP0s cores.       */
79
80volatile uint32_t   global_count;           /* Number of cores expected in
81                                               global barrier.              */
82
83volatile uint32_t   local_barrier;          /* Used by CP0 to synchronize
84                                               with local CPi.              */
85
86volatile uint32_t   boot_cluster_ready;     /* Modified by bscpu to report
87                                               that the boot cluster is
88                                               ready.                       */
89
90// kernel image memory layout.
91uint32_t ktext_base;                        /* ktext segment base address.  */
92uint32_t ktext_end;                         /* ktext segment end address.   */
93uint32_t kdata_base;                        /* kdata segment base address.  */
94uint32_t kdata_end;                         /* kdata segment end address.   */
95
96uint32_t kernel_entry;                      /* Kernel entry point.          */
97
98// Extern variables.
99extern void boot_entry();                   /* boot_loader() function       */
100
101/****************************************************************************
102 *                           Internal functions.                            *
103 ****************************************************************************/
104
105char * device_type_str( uint32_t dev_type )
106{
107    if     ( dev_type == DEV_TYPE_RAM     ) return "RAM";
108    else if( dev_type == DEV_TYPE_DMA     ) return "DMA";
109    else if( dev_type == DEV_TYPE_FBF     ) return "FBF";
110    else if( dev_type == DEV_TYPE_IOB     ) return "IOB";
111    else if( dev_type == DEV_TYPE_IOC_BDV ) return "IOC_BDV";
112    else if( dev_type == DEV_TYPE_IOC_HBA ) return "IOC_HBA";
113    else if( dev_type == DEV_TYPE_IOC_SDC ) return "IOC_SDC";
114    else if( dev_type == DEV_TYPE_IOC_SPI ) return "IOC_SPI";
115    else if( dev_type == DEV_TYPE_IOC_RDK ) return "IOC_RDK";
116    else if( dev_type == DEV_TYPE_MMC     ) return "MMC";
117    else if( dev_type == DEV_TYPE_MWR_CPY ) return "MWR_CPY";
118    else if( dev_type == DEV_TYPE_MWR_GCD ) return "MWR_GCD";
119    else if( dev_type == DEV_TYPE_MWR_DCT ) return "MWR_DCT";
120    else if( dev_type == DEV_TYPE_NIC     ) return "NIC";
121    else if( dev_type == DEV_TYPE_ROM     ) return "ROM";
122    else if( dev_type == DEV_TYPE_SIM     ) return "SIM";
123    else if( dev_type == DEV_TYPE_TIM     ) return "TIM";
124    else if( dev_type == DEV_TYPE_TTY     ) return "TTY";
125    else if( dev_type == DEV_TYPE_XCU     ) return "XCU";
126    else if( dev_type == DEV_TYPE_PIC     ) return "PIC";
127    else if( dev_type == DEV_TYPE_CMA     ) return "CMA";
128    else                                    return "UNDEFINED";
129}
130
131/****************************************************************************
132 * This function loads the arch_info.bin file into the boot cluster memory.
133 ****************************************************************************/
134static void boot_archinfo_load()
135{
136    archinfo_header_t* header = (archinfo_header_t*)ARCHINFO_BASE; 
137   
138    // Load file into memory
139    if (boot_fat32_load(ARCHINFO_PATHNAME, ARCHINFO_BASE, ARCHINFO_MAX_SIZE))
140    {
141        boot_printf("\n[BOOT ERROR]: boot_archinfo_load(): "
142                    "<%s> file not found\n",
143                    ARCHINFO_PATHNAME);
144        boot_exit();
145    }
146
147    if (header->signature != ARCHINFO_SIGNATURE)
148    {
149        boot_printf("\n[BOOT_ERROR]: boot_archinfo_load(): "
150                    "<%s> file signature should be %x\n",
151                    ARCHINFO_PATHNAME, ARCHINFO_SIGNATURE);
152        boot_exit();
153    }
154
155#if DEBUG_BOOT_INFO
156boot_printf("\n[BOOT] file %s loaded at %l\n",
157            ARCHINFO_PATHNAME , ARCHINFO_BASE );
158#endif
159
160} // boot_archinfo_load()
161
162/****************************************************************************
163 * This function loads the 'kernel.elf' file into the boot cluster memory   *
164 * bank, analyzes it then places the kernel image at the temporary physical *
165 * memory address KERN_IMG_TMP_BASE since other processors are still        *
166 * executing the preloader code (which means that the kernel image cannot   *
167 * be placed now at its final memory location starting at address 0x0.      *
168 ****************************************************************************/
169static void boot_kernel_load()
170{
171    Elf32_Ehdr* elf_header;         /* Pointer on 'kernel.elf' header.      */
172    Elf32_Phdr* program_header;     /* Pointer on 'kernel.elf' program
173                                       header.                              */
174    uint32_t    phdr_offset;        /* Program header offset in
175                                       'kernel.elf' file.                   */
176    uint32_t    segments_nb;        /* Total number of segments in
177                                       'kernel.elf' file.                   */
178
179    uint32_t    seg_src_addr;       /* Segment address in 'kernel.elf'
180                                       file (source).                       */
181    uint32_t    seg_paddr;          /* Physical address at which the
182                                       first byte of the segment resides
183                                       in memory.                           */
184    uint32_t    seg_offset;         /* Offset from the beginning of
185                                       'kernel.elf' file to the segment's
186                                       first byte.                          */ 
187    uint32_t    seg_filesz;         /* Segment's number of bytes in
188                                       'kernel.elf' file.                   */ 
189    uint32_t    seg_memsz;          /* Segment's number of bytes in the
190                                       memory image.                        */
191
192    uint32_t    seg_id;             /* Iterator for program header scanning
193                                       loop.                                */
194
195    /* Loading file into memory. */
196    if (boot_fat32_load(KERNEL_PATHNAME, KERN_BASE, KERN_MAX_SIZE))
197    {
198        boot_printf("\n[BOOT ERROR]: boot_kernel_load(): "
199                    "<%s> file not found\n",
200                    KERNEL_PATHNAME);
201        boot_exit();
202    }
203
204    /*
205     * Initializing pointer to header which is the first element of the
206     * .elf file.
207     */
208    elf_header = (Elf32_Ehdr*)KERN_BASE;
209
210    /* Signature problem, abort program !!! */
211    if ((elf_header->e_ident[EI_MAG0] != ELFMAG0)   ||
212        (elf_header->e_ident[EI_MAG1] != ELFMAG1)   ||
213        (elf_header->e_ident[EI_MAG2] != ELFMAG2)   ||
214        (elf_header->e_ident[EI_MAG3] != ELFMAG3))
215    {
216        boot_printf("\n[BOOT_ERROR]: boot_kernel_load(): "
217                    "<%s> is not an ELF file\n",
218                    KERNEL_PATHNAME);
219        boot_exit();
220    }
221
222    /* Getting the program header table offset and the number of segments. */
223    phdr_offset     = elf_header->e_phoff;
224    segments_nb     = elf_header->e_phnum;
225
226    /* Getting the program header table pointer. */
227    program_header  = (Elf32_Phdr*)(KERN_BASE + phdr_offset);
228
229    /* Looking for loadable segments. */
230    for (seg_id = 0; seg_id < segments_nb; seg_id++) 
231    {
232        // Found one:
233        if (program_header[seg_id].p_type == PT_LOAD)
234        {
235            // Getting its attributes.
236            seg_paddr    = program_header[seg_id].p_paddr;   
237            seg_offset   = program_header[seg_id].p_offset;
238            seg_filesz   = program_header[seg_id].p_filesz;
239            seg_memsz    = program_header[seg_id].p_memsz;
240
241            // Load it to its appropriate physical memory address.
242            seg_src_addr = (uint32_t)KERN_BASE + seg_offset;
243            boot_memcpy((void*)(KERN_IMG_TMP_BASE + seg_paddr), 
244                        (void*)seg_src_addr, 
245                               seg_filesz);
246
247            // Fill remaining memory with zero if (filesz < memsz).
248            boot_memset((void*)(KERN_IMG_TMP_BASE + seg_paddr + seg_filesz),
249                                0,
250                                seg_memsz - seg_filesz);
251           
252            /*
253             * Note: we suppose that the 'kernel.elf' file contains only 2
254             * loadable segments ktext + kdata and that the main
255             * difference between these two is the WRITE permission: ktext
256             * contains read-only instructions and read_only data,
257             * while kdata contains writable data.
258             */
259
260            // Get ktext segment base and end addresses.
261            if ((program_header[seg_id].p_flags & PF_W) == 0)
262            {
263                ktext_base = seg_paddr;
264                ktext_end  = seg_paddr + seg_memsz;
265            }
266
267            // Get kdata segment base and end addresses.
268            else
269            {
270                kdata_base = seg_paddr;
271                kdata_end  = seg_paddr + seg_memsz;
272            }
273        }
274    }
275
276    // Get the entry point for kernel code.
277    kernel_entry = (uint32_t)elf_header->e_entry;
278
279} // boot_kernel_load()
280
281/****************************************************************************
282 * This function initializes the local 'boot_info_t' structure.             *
283 * @ boot_info  : pointer to local boot_info_t structure                    *
284 * @ cxy        : cluster identifier                                        *
285 ****************************************************************************/
286static void boot_info_init( boot_info_t * boot_info,
287                            cxy_t         cxy )
288{
289    archinfo_header_t  * header;       
290    archinfo_core_t    * core_base;     
291    archinfo_cluster_t * cluster_base; 
292    archinfo_device_t  * device_base;
293    archinfo_irq_t     * irq_base; 
294
295    archinfo_cluster_t * cluster; 
296    archinfo_core_t    * core;
297    uint32_t             core_id; 
298    archinfo_device_t  * device;
299    uint32_t             device_id;
300    archinfo_irq_t     * irq; 
301    uint32_t             irq_id;
302 
303    boot_device_t      * boot_dev; 
304
305    // get pointer on ARCHINFO header
306    header = (archinfo_header_t*)ARCHINFO_BASE;
307
308    // Initialize global platform parameters
309    boot_info->x_size       = header->x_size;
310    boot_info->y_size       = header->y_size;
311    boot_info->x_width      = header->x_width;
312    boot_info->y_width      = header->y_width;
313    boot_info->paddr_width  = header->paddr_width;
314    boot_info->io_cxy       = header->io_cxy;
315
316    // Initialize kernel segments
317    boot_info->kernel_code_start = ktext_base;
318    boot_info->kernel_code_end   = ktext_end;
319    boot_info->kernel_data_start = kdata_base;
320    boot_info->kernel_data_end   = kdata_end;
321
322    // Initialize specific cluster parameter
323    core_base    = archinfo_get_core_base   (header);
324    cluster_base = archinfo_get_cluster_base(header);
325    device_base  = archinfo_get_device_base (header);
326    irq_base     = archinfo_get_irq_base    (header);
327
328    // lopp on the clusters to find local cluster descriptor
329    for (cluster =  cluster_base;
330         cluster < &cluster_base[header->x_size * header->y_size];
331         cluster++)
332    {
333        if (cluster->cxy != cxy) continue;
334
335        boot_info->cxy          = cluster->cxy;
336        boot_info->cores_nr     = cluster->cores;
337        boot_info->devices_nr   = cluster->devices;
338
339#if DEBUG_BOOT_INFO
340boot_printf("\n[BOOT] build boot_info for cluster %x : %d cores / %d devices\n",
341            cluster->cxy , cluster->cores , cluster->devices );
342#endif
343        // Initialize array of core descriptors
344        for (core = &core_base[cluster->core_offset], core_id = 0;
345             core < &core_base[cluster->core_offset + cluster->cores];
346             core++, core_id++)
347        {
348            boot_info->core[core_id].gid = (gid_t)core->gid;
349            boot_info->core[core_id].lid = (lid_t)core->lid; 
350            boot_info->core[core_id].cxy = (cxy_t)core->cxy;
351
352#if DEBUG_BOOT_INFO
353boot_printf("  - core %x : cxy = %x / lid = %d\n", 
354            core->gid , core->cxy , core->lid );
355#endif
356
357        }
358
359        // Initialize array of device descriptors
360        for (device = &device_base[cluster->device_offset], device_id = 0;
361             device < &device_base[cluster->device_offset + cluster->devices];
362             device++, device_id++)
363        {
364            boot_dev = &boot_info->dev[device_id];
365
366            boot_dev->type       =         device->type;
367            boot_dev->base       = (xptr_t)device->base;
368            boot_dev->size       =         device->size;
369            boot_dev->channels   =         device->channels;
370            boot_dev->param0     =         device->arg0;   
371            boot_dev->param1     =         device->arg1;   
372            boot_dev->param2     =         device->arg2;   
373            boot_dev->param3     =         device->arg3;   
374            boot_dev->irqs       =         device->irqs;   
375
376#if DEBUG_BOOT_INFO
377boot_printf("  - device %s : base = %l / size = %d / channels = %d / irqs = %d\n",
378            device_type_str( device->type ) , device->base , device->size ,
379            device->channels , device->irqs );   
380#endif
381
382            // Initialize information about physical memory in cluster
383            if (device->type == DEV_TYPE_RAM)
384            {
385                // Compute total number of physical memory pages in cluster
386                boot_info->pages_nr = device->size >> CONFIG_PPM_PAGE_SHIFT;
387
388                // Get the last address allocated for the kernel segments
389                uint32_t end = (ktext_end < kdata_end) ? kdata_end : ktext_end;
390
391                // Computing the number of pages allocated for the kernel.
392                if( (end & CONFIG_PPM_PAGE_MASK) == 0 )
393                {
394                    boot_info->pages_offset = end >> CONFIG_PPM_PAGE_SHIFT;
395                }
396                else
397                {
398                    boot_info->pages_offset = (end >> CONFIG_PPM_PAGE_SHIFT) + 1;
399                }
400            }
401           
402            // Initialize array of irq descriptors for XCU
403            if (device->type == DEV_TYPE_XCU) 
404            {
405                for (irq_id = 0; irq_id < CONFIG_MAX_HWIS_PER_ICU; irq_id++)
406                {
407                    boot_dev->irq[irq_id].valid  = 0;
408                }
409
410                for (irq = &irq_base[device->irq_offset];
411                     irq < &irq_base[device->irq_offset + device->irqs];
412                     irq++)
413                {
414                    boot_dev->irq[irq->port].valid    = 1;
415                    boot_dev->irq[irq->port].dev_type = irq->dev_type;
416                    boot_dev->irq[irq->port].channel  = irq->channel;
417                    boot_dev->irq[irq->port].is_rx    = irq->is_rx;
418
419#if DEBUG_BOOT_INFO
420boot_printf("    . irq_port = %d / source = %s / channel = %d / is_rx = %d\n",
421            irq->port , device_type_str( irq->dev_type ) , irq->channel , irq->is_rx );
422#endif
423
424                }
425            }
426
427            // Initialize array of irq descriptors for PIC
428            if (device->type == DEV_TYPE_PIC) 
429            {
430                for (irq_id = 0; irq_id < CONFIG_MAX_IRQS_PER_PIC; irq_id++)
431                {
432                    boot_dev->irq[irq_id].valid  = 0;
433                }
434
435                for (irq = &irq_base[device->irq_offset];
436                     irq < &irq_base[device->irq_offset + device->irqs];
437                     irq++)
438                {
439                    boot_dev->irq[irq->port].valid    = 1;
440                    boot_dev->irq[irq->port].dev_type = irq->dev_type;
441                    boot_dev->irq[irq->port].channel  = irq->channel;
442                    boot_dev->irq[irq->port].is_rx    = irq->is_rx;
443
444#if DEBUG_BOOT_INFO
445boot_printf("    . irq_port = %d / source = %s / channel = %d / is_rx = %d\n",
446            irq->port , device_type_str( irq->dev_type ) , irq->channel , irq->is_rx );
447#endif
448
449                }
450            }
451        }
452
453#if DEBUG_BOOT_INFO
454boot_printf("  - ram : number of pages = %x / first free page = %x\n",
455            boot_info->pages_nr , boot_info->pages_offset );
456#endif
457
458    }
459} // boot_info_init()
460
461/****************************************************************************
462 * This function is executed by all cores in order to check their           *
463 * local boot_info_t structure.                                             *
464 * @ boot_info  : pointer to local 'boot_info_t' structure to be checked.   *
465 * @ lid        : core local identifier, index the core descriptor table.   *
466 ****************************************************************************/
467static void boot_check_core( boot_info_t * boot_info, 
468                             lid_t         lid)
469{
470    gid_t         gid;        // global hardware identifier of this core
471    boot_core_t * this;       // BOOT_INFO core descriptor of this core. 
472
473    // Get core hardware identifier
474    gid = (gid_t)boot_get_procid();
475
476    // get pointer on core descriptor
477    this = &boot_info->core[lid];
478
479    if ( (this->gid != gid) ||  (this->cxy != boot_info->cxy) )
480    {
481        boot_printf("\n[BOOT ERROR] in boot_check_core() :\n"
482                    " - boot_info cxy = %x\n"
483                    " - boot_info lid = %d\n"
484                    " - boot_info gid = %x\n"
485                    " - actual    gid = %x\n",
486                    this->cxy , this->lid , this->gid , gid );
487        boot_exit();
488    }
489
490} // boot_check_core()
491
492/****************************************************************************
493 * This function is called by the bscpu to activate all other CP0s.         *
494 * It returns the number of CP0s actually activated.
495 ****************************************************************************/
496static uint32_t boot_wake_cp0()
497{
498    archinfo_header_t*  header;         /* Pointer on ARCHINFO header.      */
499    archinfo_cluster_t* cluster_base;   /* Pointer on ARCHINFO cluster
500                                           base.                            */ 
501    archinfo_cluster_t* cluster;        /* Iterator for waking CP0 loop.    */
502    archinfo_device_t*  device_base;    /* Pointer on ARCHINFO peripheral
503                                           device base.                     */
504    archinfo_device_t*  device;         /* Iterator for finding XICU device
505                                           loop.                            */
506
507    uint32_t            cp0_nb = 0;     /* Number of CP0 woken up.          */
508
509    header       = (archinfo_header_t*)ARCHINFO_BASE;
510    cluster_base = archinfo_get_cluster_base(header);
511    device_base  = archinfo_get_device_base (header); 
512
513    // loop on all clusters
514    for (cluster = cluster_base;
515         cluster < &cluster_base[header->x_size * header->y_size];
516         cluster++)
517    {
518        // Skip boot cluster.
519        if (cluster->cxy == BOOT_CORE_CXY)
520            continue;
521           
522        // Skip clusters without core (thus without CP0).
523        if (cluster->cores == 0)
524            continue;
525
526        // Skip clusters without device (thus without XICU).
527        if (cluster->devices == 0)
528            continue;
529
530        // Look for the XICU device associated to the CP0 of this cluster
531        // then send an WTI to it in order to wake it up.
532        for (device = &device_base[cluster->device_offset];
533             device < &device_base[cluster->device_offset + cluster->devices];
534             device++)
535        {
536            if (device->type == DEV_TYPE_XCU)
537            {
538                boot_remote_sw((xptr_t)device->base, (uint32_t)boot_entry);
539                cp0_nb++;
540            }
541        }
542    }
543    return cp0_nb;
544
545} // boot_wake_cp0()
546
547/****************************************************************************
548 * This function is called by all CP0 to activate all local CPi cores.      *
549 * @ boot_info  : pointer to local 'boot_info_t' structure, used to find    *
550 *                the XICU device associated with local CPi base addresses. *
551 ****************************************************************************/
552static void boot_wake_local_cores(boot_info_t* boot_info)
553{
554    boot_device_t*  device;         // Iterator on devices
555    unsigned int    core_id;        // Iterator on cores
556
557    // loop on devices to find XCU
558    for (device = &boot_info->dev[0];
559         device < &boot_info->dev[boot_info->devices_nr];
560         device++)
561    {
562        if (device->type == DEV_TYPE_XCU)
563        {
564            // loop on cores
565            for (core_id = 1; core_id < boot_info->cores_nr; core_id++)
566                boot_remote_sw((xptr_t) (device->base + (core_id << 2)),
567                               (uint32_t)boot_entry); 
568        }
569    }
570} // boot_wake_local_cores()
571
572/****************************************************************************
573 *                               API functions.                             *
574 ****************************************************************************/
575
576/****************************************************************************
577 * This main function of the boot-loader is called by the  boot_entry() 
578 * function, and executed by all cores.
579 * The arguments values are computed by the boot_entry code.
580 * @ lid    : core local identifier in its cluster,
581 * @ cxy    : cluster identifier,
582 ****************************************************************************/
583void boot_loader( lid_t lid, 
584                  cxy_t cxy )
585{
586    boot_info_t * boot_info;   // Pointer on local boot_info_t structure
587    uint32_t     local_count;  // Number of cores expected in local barrier                                  */
588
589    if (lid == 0) 
590    {
591        /**************************************
592         * PHASE ONE: only bscpu executes it. *
593         **************************************/
594        if (cxy == BOOT_CORE_CXY)
595        {
596            boot_printf("\n[BOOT] Starting on core[%d] in cluster %x at cycle %d\n",
597                        lid, cxy, boot_get_proctime());
598
599            // Initialize IOC driver
600            if      (USE_IOC_BDV) boot_bdv_init();
601            else if (USE_IOC_HBA) boot_hba_init();
602            /*
603            else if (USE_IOC_SDC) boot_sdc_init();
604            else if (USE_IOC_SPI) boot_spi_init();
605            */
606            else if (!USE_IOC_RDK)
607            {
608                boot_printf("\n[BOOT ERROR] boot_loader(): "
609                            "No IOC driver\n"
610                           );
611                boot_exit();
612            }
613
614            // Initialize simplified version of FAT32.
615            boot_fat32_init();
616
617            // Load the arch_info.bin file into memory.
618            boot_archinfo_load();
619
620            // Load the 'kernel.elf' file into memory.
621            boot_kernel_load();
622
623            // Get local 'boot_info_t' structure base address.
624            // It is the first structure in the .kdata segment.
625            boot_info = (boot_info_t*)(KERN_IMG_TMP_BASE + kdata_base);
626
627            // Signature problem, abort program !!!
628            if (boot_info->signature != BOOT_INFO_SIGNATURE)
629            {
630                boot_printf("\n[BOOT] boot_loader(): "
631                            "boot_info signature should be %x\n",
632                            BOOT_INFO_SIGNATURE);
633                boot_exit();
634            }
635
636            // Initialize local 'boot_info_t' structure.
637            boot_printf("\n[BOOT] boot_loader(): "
638                        "Initializing the local boot_info_t structure "
639                        "at cycle %d\n",
640                        boot_get_proctime());
641
642            boot_info_init(boot_info, cxy);
643
644            // Check core information.
645            boot_check_core(boot_info, lid);
646
647            // Set the barrier.
648            boot_cluster_ready = 0;
649
650            // Activate other CP0s
651            boot_printf("\n[BOOT] boot_loader(): "
652                        "Waking other CP0 up at cycle %d\n",
653                        boot_get_proctime());
654
655            global_count = boot_wake_cp0();
656
657            // Wait until all CP0s ready to enter kernel.
658            boot_printf("\n[BOOT] boot_loader(): "
659                        "Waiting for other %d CP0 at cycle %d\n",
660                        global_count, boot_get_proctime());
661
662            boot_barrier(XPTR(BOOT_CORE_CXY, &global_barrier), 
663                         global_count);
664
665            // activate other local cores of the boot cluster.
666            local_barrier = 0;
667            boot_printf("\n[BOOT] boot_loader(): "
668                        "Waking other CPi up at cycle %d\n",
669                        boot_get_proctime());
670
671            boot_wake_local_cores(boot_info);
672
673            // Wait until all other local cores are ready
674            boot_printf("\n[BOOT] boot_loader(): "
675                        "Waiting for other %d CPi at cycle %d\n",
676                        boot_info->cores_nr - 1, boot_get_proctime());
677
678            local_count = boot_info->cores_nr - 1;
679            while (local_barrier != local_count);
680
681            // Move the local kernel image at address 0x0 (erase preloader code).
682            boot_printf("\n[BOOT] boot_loader(): "
683                        "Moving the kernel image and erasing the preloader"
684                        "at cycle %d\n",
685                        boot_get_proctime());
686
687            // ktext segment.
688            boot_memcpy((void*)ktext_base,
689                        (void*)(KERN_IMG_TMP_BASE + ktext_base),
690                        ktext_end - ktext_base);
691
692            // kdata segment.
693            boot_memcpy((void*)kdata_base,
694                        (void*)(KERN_IMG_TMP_BASE + kdata_base),
695                        kdata_end - kdata_base);
696           
697            // activate other local cores.
698            boot_cluster_ready = 1;
699            boot_printf("\n[BOOT] boot_loader(): "
700                        "Everything is set, jumping to the kernel "
701                        "at cycle %d\n",
702                        boot_get_proctime());
703        }
704        /****************************************************
705         * PHASE TWO: all CP0s other than bscpu execute it. *
706         ****************************************************/
707        else
708        {
709            /*
710             * Note: at this point, we cannot access the global variables of
711             * this boot code since all the address extension registers for
712             * DATA are pointing to their local cluster in order to have
713             * access to the local stack and execute this C code.
714             * However, all the address extension registers for INSTRUCTIONS
715             * are still pointing to the boot cluster, thus we can access
716             * and call functions defined in the boot code, for example
717             * boot_remote_memcpy().
718             */
719
720            // Copy the boot-loader binary code 'boot.elf' into the local memory
721            boot_remote_memcpy(XPTR(cxy,           BOOT_BASE),
722                               XPTR(BOOT_CORE_CXY, BOOT_BASE),
723                               (unsigned int)BOOT_MAX_SIZE);
724
725            /*
726             * Note: from now on, it is safe to refer to the boot code global variables
727             * such as the base address and size of the kernel segments.
728             */
729
730            // switch to the INSTRUCTION local memory space, 
731            // to avoid contention at the boot cluster.
732            asm volatile("mtc2  %0, $25" :: "r"(cxy));
733
734            // Copy the 'arch_info.bin' file into the local memory.
735            boot_remote_memcpy(XPTR(cxy,           ARCHINFO_BASE),
736                               XPTR(BOOT_CORE_CXY, ARCHINFO_BASE),
737                               (unsigned int)ARCHINFO_MAX_SIZE);
738
739            // Copy the kernel image into local memory at address 0x0.
740            // ktext segment.
741            boot_remote_memcpy(XPTR(cxy, ktext_base),
742                               XPTR(BOOT_CORE_CXY, KERN_IMG_TMP_BASE + ktext_base),
743                               ktext_end - ktext_base);
744            // kdata segment.
745            boot_remote_memcpy(XPTR(cxy, kdata_base),
746                               XPTR(BOOT_CORE_CXY, KERN_IMG_TMP_BASE + kdata_base),
747                               kdata_end - kdata_base);
748
749            // Get local 'boot_info_t' structure base address.
750            // This is the first structure in the kdata segment.
751            boot_info = (boot_info_t*)kdata_base;
752
753            // Initialize local boot_info_t structure.
754            boot_info_init(boot_info, cxy);
755
756            // Check core information.
757            boot_check_core(boot_info, lid);
758
759            // Activateall other local CPi cores in this cluster.
760            local_barrier = 0;
761            boot_wake_local_cores(boot_info);
762
763            // Waiting until all other local cores ready
764            local_count = boot_info->cores_nr - 1;
765            while (local_barrier != local_count);
766
767            // All cores in this cluster are ready to enter kernel.
768            boot_barrier(XPTR(BOOT_CORE_CXY, &global_barrier), 
769                         global_count);
770        }
771    }
772    else
773    {
774        /***************************************************************
775         * PHASE THREE: all non CP0 cores in all clusters execute it.  *
776         **************************************************************/
777
778        if (cxy == BOOT_CORE_CXY)  // boot cluster only
779        {
780            // Report to the local CP0 that CPi is ready
781            boot_atomic_add((int32_t*)&local_barrier, 1);
782
783            // wait completion of kernel image move in  boot cluster
784            while (boot_cluster_ready != 1);
785
786            // Check core information
787            boot_info = (boot_info_t*)kdata_base;
788            boot_check_core(boot_info, lid);
789        }
790        else                      // other clusters
791        {
792            // Switch to the INSTRUCTIONS local memory space
793            // to avoid contention at the boot cluster.
794            asm volatile("mtc2  %0, $25" :: "r"(cxy));
795
796            // Report to the local CP0 that CPi is ready
797            boot_atomic_add((int32_t*)&local_barrier, 1);
798
799            // Check core information
800            boot_info = (boot_info_t*)kdata_base;
801            boot_check_core(boot_info, lid);
802        }
803    }
804
805    // Jump to the kernel code.
806    asm volatile("jr   %0" :: "r"(kernel_entry));
807
808} // boot_loader()
Note: See TracBrowser for help on using the repository browser.