프로젝트 주제 발표 - 임베디드 실시간 운영체제
Download
Report
Transcript 프로젝트 주제 발표 - 임베디드 실시간 운영체제
리눅스 커널 분석
- setup.S 전반전 -
2007. 5. 19
리종우
setup.S 개요
부트로더에 의해 실행되는 리눅스 커널의 엔트리
0x90200에 로드됨
하드웨어 장치 초기화
커널 프로그램이 실행될 수 있는 환경 설정
2
setup.S code
start : 여기서 부터 시작
- jmp trampoline
trampoline
- call start_of_setup
3
setup.S code (con`t)
start_of_setup
- slave 디스크의 타입 및 섹터수 확인
movw
$0x01500, %ax
movb$0x81, %dl
: 81 - disk1
int $0x13
: int 13-15
- setup.S의 마지막에 위치한 signature 확인 : setup.S가 제대로 로딩되었는가
cmpw
$SIG1, setup_sig1
jne bad_sig
: 0xAA55
cmpw
$SIG2, setup_sig2
jne bad_sig
: 0x5A5A
jmp good_sig1
4
setup.S code (con`t)
good_sig
- big kernel인지 확인
#ifndef __BIG_KERNEL__
.byte 0
#else
.byte LOADED_HIGH
#endif
testb $LOADED_HIGH, %cs:loadflags
: big kernel이면 loadflags가 1로
jz loader_ok
: big kernel이 아니면 old 로더에서 문제없음, loader_ok로
- old 로더인지 확인
cmpb $0, %cs:type_of_loader
: type_of_loader가 0이면 old 로더
jnz loader_ok
: old 로더가 아니면 loader_ok로
- big kernel이고 old 로더일 경우에는 panic 메시지 출력 후 무한루프
lea loader_panic_mess, %si
call prtstr
jmp no_sig_loop
loader_panic_mess: .string "Wrong loader, giving up..."
5
setup.S code (con`t)
loader_ok : long mode 가능 여부 확인
- CPUID 명령어 지원여부 확인
“ The ID flag (bit 21) in the EFLAGS register indicates support for the CPUID
instruction. If a software procedure can set and clear this flag, the processor
executing the procedure supports the CPUID instruction.
pushfl
popl %eax
movl %eax, %ebx
: eax, ebx에 eflags값 저장
xorl $0x200000, %eax
: eax의 21번 비트 반전
pushl %eax
popfl
: 21번이 반전된 eax값을 eflags에 저장
pushfl
popl %eax
: eflags를 다시 eax에 저장
cmpl %eax,%ebx
jz
no_longmode
: eax와 ebx를 비교하여 21번이 반전되었는가 확인
: 반전되지 않았다면 cpuid를 지원하지 않음
6
setup.S code (con`t)
loader_ok (con`t)
- CPU 타입 확인
movl $0x0,%eax
cpuid
cmpl $0x1,%eax
jb no_longmode
xor %di,%di
cmpl $0x68747541,%ebx
jnz noamd
cmpl $0x69746e65,%edx
jnz noamd
cmpl $0x444d4163,%ecx
jnz noamd
mov $1, %di
: eax에 0h를 넣고 cpuid를 수행하면
: Basic CPUID information
: eax가 1보다 작으면 no_longmode로
: DI를 0으로
: AuthenticAMD 문자열 반환
: 0x68747541 == "htuA"
: 0x69746e65 == "itne" */
: 0x444d4163 == "DMAc" */
: DI가 1이면 AMD임을 나타내고, 0이면 AMD가 아님
7
setup.S code (con`t)
noamd
- CPU 확장정보 확인
movl $0x1,%eax
: eax에 1h를 넣고 cpuid를 수행하면
cpuid
: edx에는 feature information이 들어옴
andl $REQUIRED_MASK1,%edx:
xorl $REQUIRED_MASK1,%edx : REQUIRED_MASK1에 해당하는 기능들이 모두 set
jnz no_longmode
: 되어있지 않으면 no_longmode로
movl $0x80000000,%eax : eax에 80000000h를 넣고 cpuid를 수행하면
cpuid
: eax에 최대의 extended function 값이 들어옴
cmpl $0x80000001,%eax
jb
no_longmode
: 보다 작으면 no_longmode로
movl $0x80000001,%eax : eax에 80000001h를 넣고 cpuid를 수행하면
cpuid
: edx에 extended feature bit가 들어옴
andl $REQUIRED_MASK2,%edx: REQUIRED_MASK2 (1 << 29)
xorl $REQUIRED_MASK2,%edx : Bit 29 : Intel EM64T available
jnz no_longmode
: 29번 bit가 set되어있지 않으면 no_longmode로
8
setup.S code (con`t)
sse_test
- SSE 지원 여부 확인
movl $1,%eax
cpuid
andl $SSE_MASK, %edx
cmpl $SSE_MASK, %edx
je
sse_ok
: eax에 1h를 넣고 cpuid를 수행하면
: edx에는 feature information이 들어옴
: SSE_MASK ((1<<25) | (1<<26))
: SSE와 SSE2 모두 지원할 때 sse_ok로
test %di,%di
jz no_longmode
: DI가 1이면 AMD, 0이면 AMD가 아님 (loader_ok 참조)
: AMD가 아니면서 SSE를 지원하지 않으면 no_longmode
9
setup.S code (con`t)
sse_test
- SSE 활성화
: SSE/SSE2를 지원안하면서 AMD일 경우 이곳 수행
movl $0xc0010015, %ecx : HWCR Register (하드웨어 설정 제어 레지스터)
rdmsr
: edx:eax에 HWCR 레지스터 값을 저장
btr $15, %eax
: eax의 15번비트(SSEDIS)을 0으로 - SSE 활성화
wrmsr
: HWCR에 edx:eax값을 저장
xor %di,%di
jmp sse_test
: DI를 0으로, test %di, %di에서 no_longmode로 가게
: SSE가 활성화가 되었는지 다시 확인
10
setup.S code (con`t)
sse_ok
- long 모드 진입을 알림
“ The operationg system notifies the BIOS what the expected operating mode
is with the Detect Target Operating Mode callback (INT 15, function EC00h).
“One of the following values in the BL register selects the operating mode.
01h – Legacy Mode Target Only.
02h – Long Mode Target Only.
03h – Mixed Mode Target.
movl $0xec00,%eax : declare target operating mode
movl $2,%ebx
: long mode
int $0x15
11
setup.S code (con`t)
Get extended memory size (three method)
- Try e820h, which lets us assemble a memory map.
- Try e801h, which returns a 32-bit memory size.
- Try 88h, which returns 0-64m.
Int 15 – E820h Return:
- CF clear if successful, CF set on error
- EAX = ‘SMAP, ES:DI = buffer filled
- EBX = next offset from which to copy or 0000 0000h if all done
e820map
struct e820map {
int nr_map
struct e820entry {
u64 addr;
u64 size;
u32 type;
} map[E820MAX];
};
: start of memory segment
: size of memory segment
: type of memory segment
: map[128]
12
setup.S code (con`t)
E820h : Get System Memory Map
xorl %eax, %eax
movl %eax, (0x1e0)
: eax를 0으로
: DS:[0x1e0] = 0,
: ALT_MEM_K, alternative mem check
#ifndef STANDARD_MEMORY_BIOS_CALL
movb %al, (E820NR)
: DS:[0x1e8] = 0, E820NR = 0x1e8,
: E820MAP의 entry 번호 0으로 초기화
meme820:
xorl %ebx, %ebx
: ebx를 0으로, next offset으로 사용됨
movw $E820MAP, %di
: di = 0x2d0(E820MAP)
jmpe820:
movl $0x0000e820, %eax
movl $SMAP, %edx
movl $20, %ecx
pushw %ds
popw %es
int $0x15
jc bail820
cmpl $SMAP, %eax
jne bail820
: EAX = 0000e820h
: EDX = 534D4150h (`SMAP`)
: size of buffer for result (20bytes)
: es = ds
: int 15- e820h 호출, 결과는 es:di에 저장됨
: 결국 es:E820MAP에 결과가 저장
: carry 플래그가 set되면 실패
: EAX에 `SMAP'에 리턴되면 e820 성공
: 그렇지 않으면 실패
13
setup.S code (con`t)
E820h : Get System Memory Map
good820:
movb(E820NR), %al
cmpb$E820MAX, %al
jae bail820
incb (E820NR)
movw
%di, %ax
addw $20, %ax
movw
%ax, %di
again820:
cmpl $0, %ebx
jne
jmpe820
: e820h가 호출될 때마다 1개의 entry가 넘어옴
: entry번호가 128(E820MAX)을 넘었는지 확인
: 최대 entry개수보다 많으면 bail820(e801호출)
: entry번호를 1씩 증가
: di = di + 20, 인덱스가 다음 엔트리를 가리키게
: 20bytes (e820entry의 크기)
: ebx 가 0(EOF)이면 e820h가 완료된 것이고
: 0이 아니면 이 ebx 값을 next offset으로
: e820h 다시 호출
14
setup.S code (con`t)
E801h : Get Memory Size
- Return: CF clear if successful, CF set on error
- AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
- BX = extended memory above 16M, in 64K blocks
- CX = configured memory 1M to 16M, in K
- DX = configured memory above 16M, in 64K blocks
meme801:
stc
xorw %cx, %cx
xorw %dx, %dx
movw $0xe801, %ax
int $0x15
jc
mem88
cmpw
$0x0, %cx
jne e801usecxdx
cmpw
$0x0, %dx
jne e801usecxdx
movw
%ax, %cx
movw
%bx, %dx
: set carry
: cx = 0
: dx = 0
: int 15, e801 call
: e801이 실패하면 carry가 set, mem88로
: cx가 0이 아니면 e801usecxdx로
: dx가 0이 아니면 e801usecxdx로
: cx,dx에 값이 리턴되지 않았다면
: ax, bx에 리턴된 메모리 크기를 cx,dx에 저장
15
setup.S code (con`t)
E801h : Get Memory Size
- Return: CF clear if successful, CF set on error
- AX = extended memory between 1M and 16M, in K (max 3C00h = 15MB)
- BX = extended memory above 16M, in 64K blocks
- CX = configured memory 1M to 16M, in K
- DX = configured memory above 16M, in 64K blocks
e801usecxdx:
andl $0xffff, %edx
: 부호확장 제거
shll $6, %edx
: edx << 6, 64K단위이기때문에 64를 곱함,1K단위로
movl %edx, (0x1e0)
: 메모리 크기를 0x1e0저장
andl $0xffff, %ecx
: 부호확장 제거
addl %ecx, (0x1e0)
: 하위 메모리의 크기도 더함
16
setup.S code (con`t)
88H : Get Extended Memory Size
- Return: CF clear if successful, CF set on error
- AX = number of contiguous KB starting at absolute address 100000h
- AH = status
- 64MB까지만 확인 가능
mem88:
movb $0x88, %ah
int $0x15
movw %ax, (2)
: 메모리의 크기는 ds:0x2번지에 저장
17
setup.S code (con`t)
Set Keyboard Repeat Rate
- Int 16, 03h : KEYBOARD - SET TYPEMATIC RATE AND DELAY
- AH = 03h
- AL = subfunction
- 05h set repeat rate and delay (AT,PS)
- BH = delay value (00h = 250ms to 03h = 1000ms)
- BL = repeat rate (00h=30/sec to 0Ch=10/sec [def] to 1Fh=2/sec)
movw $0x0305, %ax
xorw %bx, %bx
int $0x16
: delay를 최소(250ms)로, repeat rate를 최대(30s)로
call video
: VGA 관련 설정을 한다
18