U - boot 분석 과 이식 (3) - U - boot stage 2 분석.

.
void startarmboot (void) 함수, 곧 두 개의 중요 한 데이터 구조 gd 가 나타 납 니 다.t 와 bdt
1、gd_t : global data 데이터 구조 정의, 파일 에 있 음 include/asm-arm/global_data.h.그 구성원 들 은 주로 전역 적 인 시스템 초기 화 매개 변수 이다.
   1. typedef struct  global_data {  
   2.     bd_t        *bd;      // struct board_info<span style="font-family:  ;">  ,      </span>  
   3.     unsigned long   flags;     // <span style="font-family:  ;">    ,           </span>  
   4.     unsigned long   baudrate;  
   5.     unsigned long   have_console;   /* serial_init() was called */  
   6.     unsigned long   reloc_off;  /* Relocation Offset */  
   7.     unsigned long   env_addr;   /* Address  of Environment struct       */  
   8.     unsigned long   env_valid;  /* Checksum of Environment valid? */  
   9.     unsigned long   fb_base;    /* base address of frame buffer */  
  10. #ifdef CONFIG_VFD  
  11.     unsigned char   vfd_type;   /* display type */  
  12. #endif  
  13. #if 0  
  14.     unsigned long   cpu_clk;    /* CPU clock in Hz!     */  
  15.     unsigned long   bus_clk;  
  16.     unsigned long   ram_size;   /* RAM size */  
  17.     unsigned long   reset_status;   /* reset status register at boot */  
  18. #endif  
  19.     void        **jt;       /* jump table */  
  20. } gd_t;  

2.、bd_t :board info
에 자리잡다,... 
include/asm-arm/u-boot.h
.판 자 를 저장 합 니 다.
   1. typedef struct bd_info {  
   2.     int         bi_baudrate;    /* serial console baudrate */  
   3.     unsigned long   bi_ip_addr; /* IP Address */  
   4.     unsigned char   bi_enetaddr[6]; /* Ethernet adress */  
   5.     struct environment_s           *bi_env;  
   6.     ulong           bi_arch_number; /* unique id for this board  <span style="font- family:  ;">  </span><span style="font- family:Times New Roman;">ID</span><span style="font-family:  ;"> </span>*/  
   7.     ulong           bi_boot_params; /* where this board expects params */  
   8.     struct              /* RAM configuration */  
   9.     {  
  10.     ulong start;  
  11.     ulong size;  
  12.     }           bi_dram[CONFIG_NR_DRAM_BANKS];  
  13. #ifdef CONFIG_HAS_ETH1  
  14.     /* second onboard ethernet port */  
  15.     unsigned char   bi_enet1addr[6];  
  16. #endif  
  17. } bd_t;  

전역 데 이 터 를 저장 할 영역 을 할당 합 니 다. 주 소 는 포인터 gd 입 니 다.
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
0 을 정리 하고 공간 을 분배 합 니 다.
memset ((void*)gd, 0, sizeof (gd_t));

gd 앞 자리 에서 gd -> bd 할당 주소
   1. gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));  

gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));0 을 정리 하고 공간 을 분배 합 니 다.
memset (gd->bd, 0, sizeof (bd_t));  
memset (gd->bd, 0, sizeof (bd_t));
일련의 초기 화 함수 실행
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {  
  •   if ((*init_fnc_ptr)() != 0) {  

  •    hang ();  
  •   }  

  •  }  
    for (init_fnc_ptr = init_sequence; *init_fnc_ptr;++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) { hang (); } }
    함수 포인터 가 가리 키 는 함수 반환 값 이 0 이 아니라면 hang () 에서 순환 을 멈 추고 초기 화 에 실패 합 니 다.
    void hang (void)  
  • {  

  •  puts ("### ERROR ### Please RESET the board ###");  
  •  for (;;);  

  • }  
    void hang (void) { puts ("### ERROR ### Please RESET the board ###"); for (;;); }
    함수 목록 은 다음 과 같 습 니 다.
    초기 화 함수 마다 정상 적 인 상황 에서 반환 값 은 0 입 니 다.
    # init_fnc_t *init_sequence[] = {  
    #  cpu_init,  /*    irq/fiq    */  
    #  board_init, /*       */  
    #  interrupt_init, /*      */  
    #  env_init,  /*   flash          */  
    #  init_baudrate, /*       */  
    #  serial_init, /*      */  
    #  console_init_f, /*        */  
    #  display_banner, /* say that we are here */ 

    이 어 NOR FLASH, LCD, 직렬 포트, 콘 솔, sd 카드, 네트워크 카드 등 을 초기 화하 고 일일이 열거 하지 않 았 다.
    드디어 중요 한 순간 이 왔 다 -- #
    순환
    [cpp] view plain copy print ?
    for (;;)  
  • {  

  •  main_loop ();  
  • }  

  • for (;;) { main_loop (); }
    계속 추적
    bootdelay 시간 내 에 키 를 누 르 고 명령 행 에 들 어 가 는 것 을 발견 하고 run command 로 명령 을 해석 합 니 다.
       1. #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)  
       2.     s = getenv ("bootdelay");  
       3.     bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;  
       4.   
       5.     debug ("### main_loop entered: bootdelay=%d

    ", bootdelay);

    CONFIG BOOTDELAY 가 정의 되 었 다 면 s 로 환경 변수 bootdelay 를 얻 은 다음 마지막 으로 커 널 을 시작 합 니 다.
       1. #ifdef CONFIG_BOOTCOUNT_LIMIT  
       2.     if (bootlimit && (bootcount > bootlimit)) {  
       3.         printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.
    ", 4. (unsigned)bootlimit); 5. s = getenv ("altbootcmd"); 6. } 7. else 8. #endif /* CONFIG_BOOTCOUNT_LIMIT */ 9. s = getenv ("bootcmd");

    CONFIG BOOTCOUNT LIMIT 는 U - boot 시작 횟수 를 설정 하 는 제한 입 니 다.
    마지막 s = getenv ("bootcmd"); 시작 매개 변 수 를 가 져 옵 니 다.
    [cpp] view plain copy print ?
    run_command (s, 0);  
    run_command (s, 0);
    시작 명령 해석 run command 함수 에서 최종 실행 명령
    [cpp] view plain copy print ?
    /* OK - call function to do the command */  
  • if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {  

  •  rc = -1;  
  • }  

  • /* OK - call function to do the command */if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { rc = -1; }
    이것 은 명령 구조 체 입 니 다. 원형 은 다음 과 같 습 니 다.
    [cpp] view plain copy print ?
    struct cmd_tbl_s {  
  •     char        *name;      /* Command Name         */  

  •     int     maxargs;             /* 최대 매개 변수 개수 */  
  •     int     repeatable; /* 명령 반복 가능 여부   */  

  •     int     (*cmd)(struct cmd_tbl_s *, int, int, char *[];/* 대응 하 는 함수 포인터 */  
  •     char        *usage;     /* Usage message    (short) */  

  • struct cmd tbl s {char * name;/* Command Name */int maxargs;/* 최대 매개 변수 개수 */int repeatable;/* 명령 중복 가능 여부 */int (* cmd) (struct cmd tbl s *, int, int, char * []);/* 대응 하 는 함수 포인터 */char * usage;/* Usage message (short) */
    정상 적 인 상황 에서 U BOOT CMD 명령 을 실행 합 니 다. U BOOT CMD 매크로 는 명령 을 정의 합 니 다. 명령 매크로 의 원형 은 다음 과 같 습 니 다.
    [cpp] view plain copy print ?
    /* 명령 매크로 U BOOT CMD */  
  • #define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \  

  • cmd_tbl_t    __u_boot_cmd_##name     Struct_Section = {#name, maxargs, rep, cmd, usage, help}  
    /* 명령 매크로 U BOOT CMD */\# define U BOOT CMD (name, maxargs, rep, cmd, usage, help)\cmd tbl t u boot cmd\#\# name Struct Section = {\# name, maxargs, rep, cmd, usage, help}
    만약 위 에 들 어 오 는 것 이 bootm 명령 이 커 널 을 시작 하 는 것 이 라면 해당 하 는 것 을 호출 할 것 입 니 다.
     U BOOT CMD 의 do bootm 함수
    [cpp] view plain copy print ?
    U_BOOT_CMD(  
  •     bootm,  CFG_MAXARGS,    1,  do_bootm,  

  •     "bootm   - boot application image from memory",  
  •     "[addr [arg ...]]    - boot application image stored in memory"  

  •     "\tpassing arguments 'arg ...'; when booting a Linux kernel,"  
  •     "\t'arg' can be the address of an initrd image"  

  • U_BOOT_CMD( bootm, CFG_MAXARGS, 1, do_bootm, "bootm - boot application image from memory", "[addr [arg ...]] - boot application image stored in memory""\tpassing arguments 'arg ...'; when booting a Linux kernel,""\t'arg' can be the address of an initrd image"
    do bootm 함수 에 서 는 switch case 로 커 널 zImage 형식, 압축 해제 방식, 운영 체제 등 을 검사 합 니 다. zImage 는 자체 적 으로 압축 을 풀 지 않 아 도 되 기 때 문 입 니 다.
    [cpp] view plain copy print ?
    switch (hdr->ih_os) {  
  •     default:            /* handled by (original) Linux case */  

  •     case IH_OS_LINUX:  
  •   

  •         do_bootm_linux  (cmdtp, flag, argc, argv,  
  •                  addr, len_ptr, verify);  

  •         break;    
    switch (hdr->ih_os) { default:/* handled by (original) Linux case */case IH_OS_LINUX: do_bootm_linux (cmdtp, flag, argc, argv, addr, len_ptr, verify); break;
    마지막 으로 Armlinux. c 에 들 어 가 는 do bootm linux 함수 가 리 눅 스 커 널 U Boot 를 시작 하 는 것 도 태그 목록 을 통 해 커 널 에 파 라 메 터 를 전달 하 는 것 입 니 다.
    [cpp] view plain copy print ?
    #ifdef CONFIG_CMDLINE_TAG  
  •     char *commandline = getenv ("bootargs");  

  • #endif  
    #ifdef CONFIG_CMDLINE_TAG char *commandline = getenv ("bootargs"); #endif
    CONFIG CMDLINE TAG 는 smdk2410. h 에서 정의 되 었 습 니 다.
    theKernel 은 커 널 에 저 장 된 주 소 를 가리 키 고 있 습 니 다. (ARM 구조의 CPU 는 보통 0x 30008000)
    /* 커 널 의 입구 함수 포인터 */
    [cpp] view plain copy print ?
    void (*theKernel)(int zero, int arch, uint params);  
    void (*theKernel)(int zero, int arch, uint params);
     
    /* 커 널 입구 주 소 를 theKernel 에 할당 하고 hdr 는 image header t 구조 체 로 uImage 머리 를 가리 키 며 ih ep 는 커 널 의 입구 점 (Entry Point) */
    [cpp] view plain copy print ?
    theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);   
    theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
    /* 마지막 으로 커 널 입구 함수 호출 입 니 다. bd -> bi arch number 는 이 판 넬 기계 유형 ID 입 니 다. bd -> bi boot params 는 커 널 에 전 달 된 매개 변수 입 니 다. 태그 목록 주소 부터 */
    [cpp] view plain copy print ?
    theKernel (0, bd->bi_arch_number, bd->bi_boot_params);  
    theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
    [cpp] view plain copy print ?
    Linux 커 널 의 작 동 을 유도 하 는 데 필요 한 몇 가지 조건:
       1. * CPU register settings //        theKernel      
       2.           o r0 = 0.  
       3.           o r1 = machine type number.  
       4.           o r2 = physical address of tagged list in system RAM.  
       5.     * CPU mode  
       6.           o All forms of interrupts must be disabled (IRQs and FIQs.)  
       7.           o The CPU must be in SVC mode. (A special exception exists for Angel.)  
       8.     * Caches, MMUs  
       9.           o The MMU must be off.  
      10.           o Instruction cache may be on or off.  
      11.           o Data cache must be off and must not contain any stale data.  
      12.     * Devices  
      13.           o DMA to/from devices should be quiesced.  
      14.     * The boot loader is expected to call the kernel image by jumping directly to the first instruction of the kernel image.  

    좋은 웹페이지 즐겨찾기