제로 부터 시작 하 는 UBOOT 의 학습 7. - 커 널 시작.
9771 단어 임 베 디 드: UBOOTUBOOT 제로 부터 의 공부.
1. UBOOT 는 누 드 프로그램 입 니 다.
UBOOT 의 본질은 복잡 한 누 드 프로그램 이다.우리 가 ARM 누 드 전집 에서 배 운 모든 누 드 프로그램 과 본질 적 으로 다 르 지 않다.
2. ARM 누 드 기기 의 16 번 째 부분 에 간단 한 셸 을 썼 는데 이것 은 바로 미니 형의 UBOOT 이다.
(1) 운영 체제 커 널 자체 가 누 드 프로그램 으로 UBOOT, 다른 누 드 프로그램 과 본질 적 으로 다 르 지 않다.(2) 차이 점 은 운영 체제 가 실 행 된 후에 소프트웨어 에 있어 커 널 층 과 응용 층 으로 나 뉘 고 분 층 된 후 두 층 의 권한 이 다르다 는 것 이다.메모리 접근 과 장치 작업 의 관리 가 더욱 정교 하고 커 널 은 각종 하드웨어 에 마음대로 접근 할 수 있 으 며 응용 프로그램 은 하드웨어 와 메모리 주소 에 만 접근 할 수 있 습 니 다.
3. 태 워 쓰기 프로그램 을 작성 할 때 특정한 곳 에 배치
(1) 완전한 소프트웨어 + 하드웨어 내장 시스템, 정지 시 (전기 가 들 어가 지 않 음) BootLoader, kernel, rootft 등 필요 한 소프트웨어 는 모두 미 러 형식 으로 시작 미디어 에 저 장 됩 니 다.
x210 은 iNAND/SD 카드 에서 실 행 될 때 DDR 메모리 에서 실 행 됩 니 다. 저장 매체 와 상 관 없 이 위의 두 상 태 는 모두 안정 적 인 상태 이 고 세 번 째 상 태 는 동적 과정 입 니 다.정지 상태 에서 운행 상태 까지 의 과정, 즉 가동 과정 이다.
(2) 동적 시작 과정 은 SD 카드 에서 DDR 메모리 로 점차적으로 옮 기 고 시작 코드 를 실행 하여 관련 하드웨어 초기 화 와 소프트웨어 구 조 를 구축 하여 최종 적 으로 실행 시의 안정 적 인 상태 에 이 르 는 것 이다.
(3) 정지 할 때 uboot. bin, zImage rootft 는 모두 SD 카드 에 있 습 니 다. 그들 은 SD 카드 의 임 의 위치 가 임의로 존재 할 수 없 기 때문에 SD 카드 에 대해 하나의 파 티 션 을 한 다음 에 각종 미 러 를 각자 의 파 티 션 에 저장 해 야 합 니 다. 이렇게 시작 하 는 과정 에서 UBOOT, 커 널 등 은 누 구 를 찾 으 러 가 는 지 알 수 있 습 니 다.
UBOOT 와 kernel 의 구분 표 가 일치 해 야 합 니 다. 그렇지 않 으 면 kernel 을 찾 을 수 없습니다.동시에 SD 카드 의 실제 사용 구역 과 같 아야 합 니 다.
4. 실행 할 때 DDR 에 링크 주소 로 불 러 와 야 합 니 다.
(1) uboot 는 첫 번 째 단계 에서 위치 재 설정 을 할 때 두 번 째 단계 (전체 UBOOT 의 미 러) 를 DDR 의 0xc3e 00000 주소 로 불 러 옵 니 다. 이 주 소 는 바로 UBOOT 의 링크 주소 입 니 다.
(2) 커 널 에 도 비슷 한 요구 가 있 습 니 다. UBOOT 에서 커 널 을 시작 하여 메모리 를 SD 카드 에서 읽 어 DDR 에 넣 습 니 다.사실은 포 지 셔 닝 을 다시 하 는 과정 입 니 다. 함부로 놓 을 수 없습니다. 커 널 의 링크 주소 에 두 어야 합 니 다. 그렇지 않 으 면 시작 할 수 없습니다. 예 를 들 어 우리 가 사용 하 는 커 널 링크 주 소 는 0x 30008000 입 니 다.
(3) 커 널 작 동 에 필요 한 작 동 매개 변수 1, UBOOT 는 무조건 작 동 합 니 다. 0 부터 작 동 하 는 2, 커 널 은 작 동 하지 않 고 자동 으로 0 부터 작 동 합 니 다. 커 널 작 동 은 다른 사람 이 도와 야 합 니 다. UBOOT 는 커 널 이 재 포 지 셔 닝 을 실현 하도록 도와 야 합 니 다.SD 카드 부터 DDR 까지 UBOOT 는 커 널 에 시동 인 자 를 제공 해 야 한다.
5. 커 널 을 시작 하 는 과정
5.1. 커 널 을 시작 하 는 첫 번 째 단계: 커 널 을 DDR 에 불 러 옵 니 다.UBOOT 는 커 널 을 시작 하려 면 2 단계 로 나 뉘 는데 첫 번 째 단 계 는 커 널 미 러 를 시작 미디어 에서 DDR 의 링크 주소 로 불 러 오 는 것 이기 때문에 커 널 은 바로 링크 주소 부터 실 행 됩 니 다.
커 널 은 위치 추적 을 고려 할 필요 가 없습니다. 커 널 은 UBOOT 와 같은 자신 을 DDR 의 링크 주소 로 불 러 올 수 있다 는 것 을 알 기 때문에 커 널 은 링크 주소 부터 실 행 됩 니 다.
5.2 정적 커 널 미 러 는 어디 에 있 습 니까?(1) SD 카드, INAND, NAND, NORFLASH 등 RAM 의 구역.일반적인 시작 시 각종 미 러 가 SD 카드 에 있 기 때문에 UBOOT 는 SD 카드 의 kernel 파 티 션 에서 커 널 미 러 를 DDR 로 읽 으 면 됩 니 다. UBOOT 명령 을 사용 하여 읽 어야 합 니 다. 예 를 들 어 X210 의 INAND 버 전 은 movi 명령 입 니 다.X210 의 nand 버 전이 낸 드 명령 입 니 다.
(2) 이러한 시작 방식 으로 DDR 을 불 러 옵 니 다. 명령 movi read kernel 30008000 을 사용 합 니 다. 그 중에서 kernel 은 UBOOT 의 kernel 파 티 션 을 말 합 니 다. 바로 UBOOT 에 규정된 SD 카드 의 한 지역 범위 입 니 다. 이 지역 범 위 는 kernel 미 러 를 저장 하도록 설계 되 었 습 니 다. 이른바 kernel 파 티 션 입 니 다.
(3) tftp/nfs 등 네트워크 다운로드 방식 으로 원 격 서버 에서 미 러 를 가 져 옵 니 다.UBOOT 는 커 널 미 러 에서 개발 판 의 SD 카드 에 녹화 되 지 않 고 호스트 서버 에 두 고 시작 해 야 할 때 네트워크 를 통 해 서버 에서 미 러 를 다운로드 해 개발 판 DDR 에 넣 는 원 격 시작 도 지원 한다.
분석 요약: 최종 결 과 는 커 널 미 러 에서 DDR 의 특정 주소 로 설정 하면 됩 니 다. 커 널 미 러 가 어떻게 DDR 에 있 든 상기 2 가지 방식 은 각각 우열 이 있 습 니 다. 제품 출하 는 SD 카드 에서 시작 하 는 것 으로 설정 되 고 고객 은 tftp 서버 를 구축 해 야 사용 할 수 있 습 니 다.tftp 다운로드 원 격 시작 방식 은 일반적으로 개발 에 사 용 됩 니 다.
6. 미 러 는 DDR 에 넣 을 주 소 는 무엇 입 니까?
커 널 은 반드시 링크 주소 에 두 어야 합 니 다. 링크 주 소 는 커 널 코드 의 링크 스 크 립 트 나 Makefile 에서 찾 아야 합 니 다.X210 은 0x 30008000 입 니 다.
7、do_bootm_linux 함수
찾 아서 dobootm_linux 함수.(1) 함 수 는 UBOOT/libarm/bootm. c 중.(2) SI 가 찾 지 못 한다 고 해서 없 는 것 은 아니 며, 검색 해 봐 야 확인 할 수 있다.(3)
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
bootm_headers_t *images)
{
ulong initrd_start, initrd_end;
ulong ep = 0;
bd_t *bd = gd->bd;
char *s;
int machid = bd->bi_arch_number; //
void (*theKernel)(int zero, int arch, uint params);
//
int ret;
#ifdef CONFIG_CMDLINE_TAG
// , bootargs
char *commandline = getenv ("bootargs");
#endif
/* */
if (images->legacy_hdr_valid)
{
ep = image_get_ep (&images->legacy_hdr_os_copy);
#if defined(CONFIG_FIT)
}
else if (images->fit_uname_os)
{
ret = fit_image_get_entry (images->fit_hdr_os,
images->fit_noffset_os, &ep);
if (ret)
{
puts ("Can't get entry point property!
");
goto error;
}
#endif
}
else
{
puts ("Could not find kernel entry point!
");
goto error;
}
// , EP theKernel
theKernel = (void (*)(int, int, uint))ep;
// machid 。
s = getenv ("machid");
if(s)
{
machid = simple_strtoul (s, NULL, 16);
printf ("Using machid 0x%x from environment
", machid);
}
ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_ARM,
&initrd_start, &initrd_end);
if (ret)
goto error;
show_boot_progress (15);
debug ("## Transferring control to Linux (at address %08lx) ...
",
(ulong) theKernel);
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
defined (CONFIG_CMDLINE_TAG) || \
defined (CONFIG_INITRD_TAG) || \
defined (CONFIG_SERIAL_TAG) || \
defined (CONFIG_REVISION_TAG) || \
defined (CONFIG_LCD) || \
defined (CONFIG_VFD) || \
defined (CONFIG_MTDPARTITION)
setup_start_tag (bd);
#ifdef CONFIG_SERIAL_TAG
setup_serial_tag (¶ms);
#endif
#ifdef CONFIG_REVISION_TAG
setup_revision_tag (¶ms);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGS
setup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAG
setup_commandline_tag (bd, commandline);
#endif
#ifdef CONFIG_INITRD_TAG
if (initrd_start && initrd_end)
setup_initrd_tag (bd, initrd_start, initrd_end);
#endif
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
setup_videolfb_tag ((gd_t *) gd);
#endif
#ifdef CONFIG_MTDPARTITION
setup_mtdpartition_tag();
#endif
setup_end_tag (bd);
#endif
/* we assume that the kernel is in place */
printf ("
Starting kernel ...
");
#ifdef CONFIG_USB_DEVICE
{
extern void udc_disconnect (void);
udc_disconnect ();
}
#endif
cleanup_before_linux ();
//
theKernel (0, machid, bd->bi_boot_params);
/* does not return */
return;
error:
do_reset (cmdtp, flag, argc, argv);
return;
}
8. 미 러 의 entry point
(1) ep 는 entry point 의 줄 임 말 입 니 다. 바로 프로그램 입구 입 니 다. 하나의 미 러 파일 의 시작 부분 은 미 러 의 시작 부분 이 아 닙 니 다. 진정한 미 러 파일 이 실 행 될 때 첫 번 째 코드 는 미 러 의 중부 에 있 는 한 바이트 에 있 습 니 다. 머리 는 일정한 오프셋 이 있 는 것 과 같 습 니 다. 이 오프셋 은 머리 정보 에 기록 되 어 있 습 니 다.
(2) 일반적으로 하나의 미 러 를 실행 하 는 것 은 첫 번 째 단계 에서 머리 정 보 를 읽 은 다음 에 머리 정보의 특정한 주소 에서 MAGIC 를 찾 는 것 이다.NUM, 이 를 통 해 미 러 종 류 를 확인 하고 두 번 째 단 계 는 미 러 를 검사 하 며 세 번 째 단 계 는 머리 정 보 를 다시 읽 습 니 다. -특정 주소 에서 이 미 러 의 각종 정보 (미 러 길이, 미 러 종류, 입구 주소) 를 알 수 있 습 니 다.네 번 째 는 우리 엔 트 리 포인트 에 가서 미 러 를 시작 합 니 다.
앞으로 우 리 는 그림 정 보 를 읽 을 때 JPG 파일 이 아 닐 수도 있 습 니 다.
(3)theKernel = (void (*)(int, int, uint))ep;ep 포인 터 를 theKernel 에 부여 하면 이 함 수 는 메모리 에 불 러 온 OS 미 러 의 실제 입구 주 소 를 가리 키 며 운영 체제 의 첫 번 째 실행 코드 입 니 다.theKernel (0, machid, bd->bi_boot_params);이 함 수 는 커 널 에 인삼 을 전달 하 는 함수 입 니 다. 첫 번 째 매개 변 수 는 0 이 고 두 번 째 매개 변 수 는 machid 입 니 다. 바로 기계 코드 입 니 다. 세 번 째 매개 변 수 는 bi 입 니 다.boot_params: UBOOT 가 시작 하 는 세 번 째 인자) UBOOT 의 마지막 코드 입 니 다.
(4) uboot 가 커 널 을 시작 할 때 기계 코드 는 커 널 에 전달 해 야 합 니 다. UBOOT 가 커 널 에 전달 하 는 기계 코드 는 어떻게 확정 합 니까?첫 번 째 순 서 는 환경 변수 machid 이 고, 두 번 째 순 서 는 gd -> bd -> bi 입 니 다.arch_num (X210 sd. h 의 하 드 인 코딩 설정)
(5) 커 널 을 시작 하려 면 반드시 인삼 을 전달 해 야 합 니 다. 110 줄 에서 144 줄 은 바로 UBOOT 가 리 눅 스 커 널 에 전달 할 매개 변수 처 리 를 준비 하고 있 습 니 다.
(6) starting kernel... 이것 은 UBOOT 의 마지막 문장 에 인쇄 된 것 입 니 다. 이 문장 이 나타 날 수 있다 면 UBOOT 의 전체 가 성공 적 이 고 커 널 미 러 도 성공 적 으로 불 러 올 수 있 습 니 다. 검사 도 통 과 했 고 입구 주소 도 찾 았 습 니 다. 실행 하려 고 했 습 니 다. 만약 에 뒤의 직렬 포트 가 출력 되 지 않 았 다 면 커 널 이 성공 적 으로 실행 되 지 않 았 다 는 것 을 의미 합 니 다.이 유 는 일반적으로 전송 참조, 커 널 이 DDR 에 있 는 로드 주소 에 문제 가 있 기 때 문 입 니 다...
9. 상세 한 설명 을 전달한다.
tag 방식 전송: (1) struct tag, tag 는 데이터 구조 로 UBOOT 와 Linux kernel 에서 tag 데이터 구 조 를 정의 하고 정 의 는 같 습 니 다.
(2)tag_header 와 tagxxx,tag_header 에서 이 tag 의 size 와 형식 인 코딩, kernel 은 tag 의 나머지 부분 을 tag 로 가 져 옵 니 다.xxx 로 처리 합 니 다.
(3)tag_start 와 tagend, kernel 이 받 은 전 삼 은 노 간 개 tag 로 구성 되 어 있 으 며, 이 tag 들 은 tagstart 시작, tag 까지끝나다
(4) tag 전 참 방식 은 Linux kernel 이 발명 한 것 입 니 다. kernel 은 저 에 게 전 참 하 는 방식 을 정 의 했 습 니 다. UBOOT 는 이러한 전 참 방식 만 실현 하여 kernel 에 전 참 할 수 있 습 니 다.
(5) 전 삼 홍 CONFIG 설정 방법SETUP_MEMORY_TAGS,tag_mem, 전송 내용 은 메모리 설정 정보 입 니 다.CONFIG_CMDLINE_TAG,tag_cmdline, 전송 내용 은 시작 명령 행 인자, 즉 UBOOT 의 환경 변수의 bootargs. CONFIG 입 니 다.MTDPARTION, 전 삼 내용 은 iNAND/SD 카드 의 구분 표 입 니 다.
사고: 커 널 은 어떻게 이런 태 그 를 얻 었 습 니까?UBOOT 는 최종 적 으로 theKernel 함 수 를 호출 하여 리 눅 스 커 널 을 실행 합 니 다. UBOOT 는 이 함 수 를 호출 합 니 다. 사실은 리 눅 스 커 널 에서 세 개의 인 자 를 전 달 했 습 니 다. 이 세 개의 인 자 는 바로 UBOOT 가 리 눅 스 커 널 에 직접 전달 하 는 세 개의 인자 입 니 다.레지스터 를 통 해 인삼 을 전달 하 다.첫 번 째 파 라미 터 는 r0 에 놓 고 두 번 째 파 라미 터 는 r1 에 놓 고 세 번 째 파 라미 터 는 r2 에 놓는다.첫 번 째 매개 변 수 는 0 으로 고정 되 고 두 번 째 매개 변 수 는 기계 코드 이 며 세 번 째 매개 변 수 는 블록 버스터 참조 tag 의 첫 번 째 주 소 를 전달 합 니 다.
이식 시 주의사항 이 필요 합 니 다.(1) UBOOT 이식 시 일반적으로 해당 매크로 만 설정 하면 됩 니 다.(2) kernel 시작 이 성공 하지 못 했 습 니 다. 전송 이 성공 하지 못 했 는 지 주의 하 십시오. 전송 이 성공 하지 못 했 는 지 먼저 UBOOT 의 bootargs 설정 이 정확 한 지 확인 하 십시오. 그 다음 에 UBOOT 가 해당 매크로 를 열 었 는 지 확인 하여 전송 을 지원 합 니 다.
2.7.8 、 UBOOT 가 커 널 을 시작 하 는 총 결 이 작 동 하 는 4 단계:
첫 번 째 단계: 커 널 을 DDR 로 옮 기 는 두 번 째 단계: 커 널 형식 교정, CRC 등 세 번 째 단계: 네 번 째 단계 로 넘 어 갈 준비: 커 널 실행
관련 함수: 1, dobootm 와 dobootm_linux 2, UBOOT 가 시작 할 수 있 는 커 널 형식: zImage uImage fdt 방식 3, 점프 와 함수 포인터 방식 으로 커 널 을 실행 합 니 다.