⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs-boot.c

📁 Linux PPCfs-boot 不错的boot程序
💻 C
字号:
/*! * @file fs-boot.c * FILE:   $Id:$ * * DESCRIPTION: *     This is the main program for the first-stage bootloader FS-BOOT for the *     PetaLinux distribution.   * *     This bootloader is targeted for reconfigurable platform and is desgined *     to be run from BRAM.  Hence, elf size must remain below 8K bytes. * *     It supports the  booting of any second-stage bootloader from *     FLASH or RAM memory, SREC image download via the uartlite *     serial interface and image write to RAM memory. * *     Note: This program requires the following hardware support: *           - XuartLite *           - BRAM >= 8Kb * * AUTHOR:  *     Benny Chen, PetaLogix <Benny.Chen@petalogix.com> * * MODIFICATION:  * * LICENSING: *     Copyright (c) 2006 PetaLogix. All rights reserved. * *  No part of this program may be reproduced or adapted in  any form  or by  *  any means, electronic or mechanical, without  permission from PetaLogix.  *  This program is  confidential and  may not be  disclosed, decompiled  or  *  reverse engineered without permission in writing from PetaLogix. * */#include "fs-boot.h"#include "srec.h"#include "time.h"/*! \brief Macro for Jump Instruction */#define GO(addr) { ((void(*)(void))(addr))(); }/*---------------------------------------------------------------------------*//*---------------------------------------------------------------------------*//* Global variables */int do_erase = 1;/*---------------------------------------------------------------------------*//* Local Function Prototype */static void uartlite_init(void);/*---------------------------------------------------------------------------*//*! * Run initialisation code to setup the opb_timer. * This routine only enables Timer 0. * * @param  None. * * @return  None. */static void opb_timer_init(void){    /*      * Initialised the timer to default value     * The default settings for the timers are:     *   - Interrupt generation disabled     *   - Count up mode     *   - Compare mode     *   - Enable Auto Reload     *   - External compare output disabled     *   - External capture input disabled     *   - Pulse width modulation disabled     *   - Timer disabled, waits for Start function to be called     */	timer_init();    return;}/*! * Run initialisation code to setup the UART for communication. * For UARTLITE, the bulk of the configuration is done in hardware. * * @param  None. * * @return  None. */static void uartlite_init(void){    /* All mode and baud setup is done in hardware level */    /* Reset FIFO and Enable Interrupt */    XUartLite_mSetControlReg(UART_BASEADDR, (XUL_CR_ENABLE_INTR    |                                           XUL_CR_FIFO_RX_RESET  |                                           XUL_CR_FIFO_TX_RESET));}/*! * This function loads boot image to RAM. * * @param  src_addr  - The address of the  bootloader image. * @param  load_addr - The address in memory to load the image. * @param  size      - The size to copy. * * @return  none. */void load_image(unsigned long src_addr , unsigned int load_addr, int size){    int i;    volatile unsigned char *dst = (unsigned char *)load_addr;    for(i = 0; i < size; i ++) {        *dst++ = *((volatile unsigned char *)(src_addr + i));     }    return;}/*! * This function implements a light weight * memcpy routine. * * @param  dst - Destination address in memory * @param  src - Source address in memory * @param  len - Length of data to copy. * * @return  None. */void fs_memcpy(volatile char *dst, char *src, int len){    int i;    for(i = 0; i < len; i++) {        *dst++ = *src++;    }    return;}/*! * Implements a blocking read character from uart. * * @param  None. * * @return  The character read. */char get_ch(void){    while(XUartLite_mIsReceiveEmpty(UART_BASEADDR));        return XUartLite_RecvByte(UART_BASEADDR);} /*! * Implements a non-blocking read char * * @param  None. * * @return  The character read. */char get_c(void){    if(XUartLite_mIsReceiveEmpty(UART_BASEADDR)) {        return '\0';    } else {        return XUartLite_RecvByte(UART_BASEADDR);    }} /*! * Sends a single character to the uart fifo. *  * @param  data - The character to send * * @return  None. */void put_ch(unsigned char data){    while (XUartLite_mIsTransmitFull(UART_BASEADDR));    XUartLite_SendByte(UART_BASEADDR, data);    return;}/*! * This routine reads each SREC line from * the UART. Each line is return via the buffer pointer 'buf'. *  * @param  buf - Pointer to buffer (buffer size = MAXSIZE + 1 for \0) * @param  len - length of buffer * * @return  int - the number of bytes read */int read_line(char *buf, int len){    char *p;    char ch;    len--;  /* leave room for \0 */    for(p = buf; p < (buf + len); ++p) {        ch = get_ch();        switch (ch) {            case '\r':            case '\n':                *p = '\0';                return (p - buf);            case '\0':            case 0x03:  /* Ctl'C */                fsprint("\n\rExiting Serial image download.\n\r");                return(-1);            default:                *p = ch;        }    }    *p = '\0';    return (p - buf);}/*! * This routine evalutate if an address is * in the FLASH memory range. *  * @param  addr - Address to evaluate. * * @return  0 - for not in FLASH * @return  1 - for in FLASH */static int is_in_flash(unsigned long addr){    if(addr >= FLASH_BASE && addr < FLASH_END) {        return 1;    } else {        return 0;    }}/*! * This routine evalutate if an address is * in the FLASH memory range. *  * @param  addr - Address to evaluate. * * @return  0 - for not in FLASH * @return  1 - for in FLASH */static int image_exist(unsigned long image_addr){	unsigned long *addr = image_addr;	/* 	 * b8b40008 corresponds to the instruction "brlid r5, locator;"	 * defined in the bootstub routine in petalinux-reloc-blob	 * This allows us to check if a valid u-boot image is in FLASH.	 * Note: any changes to the bootstub code will need to update this. 	 */	if (*addr == 0xb8b40008) {        return 1;    } else {        return 0;    }}/*! * Loads the SREC bootloader image from the serial UART,  * decodes the SREC line and write it to FLASH or RAM. *  * @param  offset - Offset to be added to the address specified in the *          SREC. * * @return  boot location of downloaded image. * @return  0 for error. */unsigned long serial_load(unsigned long offset){    char srec_buffer[SREC_MAX_RECLEN + 1];  /* buffer for one S-Record       */    char    binbuf[SREC_MAX_BINLEN];        /* buffer for binary data        */    int     binlen;                         /* no. of data bytes in S-Rec.   */    int     type;                           /* return code for record type   */    unsigned long   addr;                   /* load address from S-Record    */    unsigned long   store_addr = 0;         /* Final location to store image */    int rtn;    int total_line = 0;    static char spin[] = "|/-\\|-";    fsprint("FS-BOOT: Waiting for SREC image....\n\r");    while ((rtn = read_line(srec_buffer, SREC_MAX_RECLEN + 1)) >= 0) {        /* Decode the SREC line */        type = decode_srec_line(srec_buffer, &binlen, &addr, binbuf);#if DEBUG        xil_printf("DEBUG:SREC Type:%d\n\r",type);        xil_printf("DEBUG:Line Length:%d\n\r",rtn);        xil_printf("DEBUG:Load Address:0x%lx\n\r",addr);        xil_printf("DEBUG:Binary Length:%d\n\r",binlen);#endif        /* Check that SREC line parsed is valid */        if (type < 0) {            fsprint("\n\rFS-BOOT: Invalid SREC!\n\r");            return 0;        }        switch (type) {        case SREC_DATA2:        case SREC_DATA3:        case SREC_DATA4:#if DEBUG            xil_printf("DEBUG:SREC_DATA:%d\n\r",type);#endif            /* obtain the final store address */            store_addr = addr + offset;            /* Check if address is in FLASH map range */            if (is_in_flash(store_addr)) {                fsprint("FS-BOOT: Destination address is in FLASH! Download Aborted.\n\r");                return 0;            } else {                /* write to SDRAM */                fs_memcpy((char *)(store_addr), binbuf, binlen);            }            break;        case SREC_END2:        case SREC_END3:        case SREC_END4:#if DEBUG	    xil_printf("DEBUG:SREC_END:0x%lx\n\r",store_addr);#endif              /* No more record */              /* Return the boot address */              return (addr + offset);        case SREC_START:#if DEBUG            xil_printf("DEBUG:SREC_START:0x%x\n\r",type);#endif            break;        default:            break;        }        total_line++;        /* Print Progress */        fsprint("\r");        put_ch(spin[(total_line % 7)]);        fsprint("\b");    }#if DEBUG    xil_printf("DEBUG:Total Line processed:%d\n\r",total_line);#endif    return 0;}/*! * Lightweight print function to avoid using stdio. *  * @param  s - The string to print. * * @return  None. */void fsprint(char *s){    while (*s) {        put_ch(*s);        s++;    }}/*---------------------------------------------------------------------------*/int main(){    unsigned long start_addr;    /* The address of the loaded image */    unsigned long image_start;   /* The address of the final boot image */    int image_maxsize = 0;    int i;    int do_srec = 0;             int boot_new = 1;		/* Default to boot new image when download occurs */#if defined(CONFIG_FS_KERNEL)    int do_kernel = 0;#endif	int bootdelay;			/* number of seconds delay */#if defined (CONFIG_FS_BOOT_DELAY)    bootdelay = CONFIG_FS_BOOT_DELAY;#else    /* Default to 3 seconds */    bootdelay = 3;#endif	     /* UART Initialisation - no printing before this */    uartlite_init();    fsprint("\n\r=================================================\n\r");    fsprint("FS-BOOT First Stage Bootloader (c) 2006 PetaLogix\n\r");    fsprint("=================================================\n\r");    /* Counter/Timer initialisation */    opb_timer_init();    fsprint("FS-BOOT: System initialisation completed.\n\r");#if defined(FS_CONFIG_KERNEL)    /* Check if we want to boot kernel or bootloader */     fsprint("FS-BOOT: Booting bootloader. Press 'k' for booting kernel.\n\r");    /* Delay x secs */    for(i = 0; i < (bootdelay * 100); i++) {        if(get_c() == 'k') {            do_kernel = 1;            break;        }		/* 10ms */		udelay(10000);    }    if(do_kernel) {        image_start = CONFIG_FS_KERN_START;        image_maxsize = CONFIG_FS_KERN_MAXSIZE;    } else#endif     {        /* Set the default bootloader boot parameters */        image_start = CONFIG_FS_BOOT_START;        image_maxsize = CONFIG_FS_BOOT_MAXSIZE;    }		/* Look to see if FLASH has valid bootloader image !!!!*/	if(image_exist(image_start)) {		fsprint("FS-BOOT: Booting from FLASH. Press 's' for image download.\n\r");		/* x second loop */		for(i = 0; i < (bootdelay * 100); i++) {			if(get_c() == 's') {				do_srec = 1;				break;			}			/* 10ms */			udelay(10000);		}	} else {		fsprint("FS-BOOT: No existing image in FLASH.  "							"Starting image download.\n\r");		do_srec = 1;	}    if(do_srec) {        /* Download SREC FILE via Serial */        start_addr = serial_load(0);        if (start_addr <= 0) {            fsprint("FS-BOOT: Image download failed.\n\r");            fsprint("FS-BOOT: Please reset target.\n\r");            return -1;         } else {            fsprint("FS-BOOT: Image download successful.\n\r");            /* Check that address is in our default bootloader partition */            if(start_addr != image_start) {                fsprint("FS-BOOT: Warning image location differ from default "                         "boot location. Image will not boot automatically after POR.\n\r");            }            fsprint("FS-BOOT: Press 'n' to boot old image.\n\r");            /* x second loop */            for(i = 0; i < (bootdelay * 100); i++) {                if(get_c() == 'n') {                    boot_new = 0;                    break;                }		        udelay(10000);            }            if(boot_new) {                fsprint("FS-BOOT: Use new image.\n\r");                /* Load using our new FLASH image */                image_start = start_addr;            }        }    }    fsprint("FS-BOOT: Booting image...\n\r");    GO(image_start);     /* Shouldn't return */    return -1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -