Maystyle :
Admin : New post
Guestbook
Local
media
Catergories
Recent Articles
Recent Comments
Recent Trackbacks
Calendar
Tag
Archive
Link
Search
 
  윈도우즈 시작 (Power on 부터 NTLDR 시작 전까지) 
작성일시 : 2009. 8. 22. 13:48 | 분류 : Windows Server/Kernel

원문 및 참고 :
http://blogs.msdn.com/ntdebugging/archive/2007/06/19/how-windows-starts-up-part-1-of-4.aspx
(번역본 : http://blogs.msdn.com/kocoreinternals/archive/2009/08/14/ntdebugging-windows.aspx)
http://blog.naver.com/juy0215?Redirect=Log&logNo=100045231750
http://dongjo.tistory.com/97
Windows Internals 4th Edition 5장 시작과 종료
http://en.wikipedia.org/wiki/Master_boot_record

본 문서는 오역 및 잘못된 이해로 인해 내용의 문제가 있을 수 있습니다.

2007년에 포스팅된 How Windows starts up part 1은 몇 주간에 걸쳐 Windows 시작에 대한 내용을 다룬다는 필자의 소개가 있었으나… 2009년이 된 지금도 여전히 Part 2까지 밖에 없습니다. ㅜㅜ

본 내용의 기본 뼈대는 How Windows starts up 을 번역해 주신 !analyze –v 블로그의 내용을 기본으로 하여 작성되었습니다.

Windows 부팅 과정은 크게 아래와 같은 단계로 이루어 집니다.

Windows 부팅 단계
1. 초기화
2. 부트 로더
3. 커널
4. 로그온

1. 초기화 단계
초기화 단계는 Power-On Self Test(POST) 와 초기 디스크 접근 단계로 나눌 수 있습니다.

1) POST
POST 동작은 컴퓨터의 제조사에 의해 바이오스에 구현되어 있습니다. 자세한 내용은 하드웨어 정보를 참고 하시기 바랍니다. 하지만 제조사에 상관 없이 일반적으로 전압 체크, 램 체크, 시스템이 사용하는 인터럽트 설정, 비디오 카드 초기화, 주변 장치 카드 검색 그리고 메모리 테스트 등을 실행 합니다. 제조사 또는 구성에 따라 다르기는 하지만 POST 가 성공할 경우 삐 소리가 한번 발생 합니다.

- POST 단계의 문제 해결
. 최신 버전의 바이오스 및 펌웨어로 업데이트되었는지 확인
. CMOS 베터리에 문제가 있을 경우 교체
. 가장 최근에 추가한 하드웨어 확인( 램, 비디오 카드, SCSI 어뎁터 등)
. 가장 최근에 추가한 RAM 제거
. 모든 어뎁터 카드 제거 후 하나씩 다시 설치
. 마더보드의 다른 슬롯으로 어뎁터 옮기기
. 계속 POST 에서 실패할 경우 제조사에 연락

2) 초기 디스크 접근
컴퓨터 바이오스에 설정 되어 있는 부트 순서에 따라 CD-ROM, 네트워크 카드, 플로피 카드, USB 디바이스 또는 하드 디스크에 의해 부팅 될 수 있습니다. 이 문서에서는 하드 디스크에서 부팅되는 일반적인 상황에 대해서 이야기 하고자 합니다.

이번 시작 단계에서 발생하는 이벤트를 이야기 하기 전에 부트 디스크에 대해서 먼저 이해 해야 합니다. 하드 디스크는 아래 그림과 같이 나타낼 수 있습니다. (아래 그림의 각 블럭 들이 크기를 나타내지는 않습니다. )

image

하드 디스크는 실린더, 헤드, 섹터로 나뉘어 집니다. 섹터는 디스크의 가작 작은 저장 단위로 보통 512 바이트 입니다. 하드 디스크의 물리적 구조에 대한 보다 자세한 정보는 아래 리소스를 참고 하시기 바랍니다.

http://www.microsoft.com/resources/documentation/windowsnt/4/server/reskit/en-us/resguide/diskover.mspx

image 
해드

image 
실린더

image
섹터

아래 두 개의 섹터는 컴퓨터가 시작되는데 아주 중요한 것으로 뒤에서 보다 자세히 다루도록 하겠습니다.

. 마스터 부트 레코드 (MBR)
. 부트 섹터

image

MBR 레코드 예시

image

MBR은 언제나 물리 디스크의 섹터1, 실린더 0, 헤드 0에 위치 합니다. (즉 512 Byte의 크기를 지니게 됩니다. ) 부트 섹터는 각 파티션의 첫 번째 섹터에 위치 합니다. 이 섹터들은 실행 코드와 코드가 실행되는데 필요한 정보를 가지고 있습니다.

섹터 숫자를 표시하는데 약간 모호함은 실린더/헤드/섹터(CHS)는 C0/H0/S1이 시작 이라는 것 입니다. 절대적인 섹터의 숫자는 0에서 시작하고 DskProbe 와 같은 툴에서도 0을 사용 합니다. 아래 문서에서 이 모호함을 설명하고 있습니다.

Q97819  Ambiguous References to Sector One and Sector Zero
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q97819

언제 디스크에서 정보를 얻어오게 될까요? MBR 은 디스크가 파티션 될 때 만들어 집니다. 부트 섹터는 볼륨을 포맷할 때 생성 됩니다.
항상 디스크의 첫번째 섹터에 위치하며 Master Boot Code로 불리는 약간의 실행 코드, 디스크 시그니처 그리고 파티션 테이블을 가지고 있습니다. 앞쪽 446 바이트는 실행파일 이고 뒤 64 바이트가 파티션 테이블, MBR 의 마지막에는 0x55AA 2바이트의 섹터의 마지막을 나타내는 구조체가 있습니다. (즉 마지막 2Byte의 값은 0x55AA 로 끝나게 됩니다.) 이 값은 확장 부트 레코드(EBR)과 부트 섹터의 마지막에도 있습니다.

아래 예는 앞으로 우리가 보게 될 MBR의 가장 마지막 데이터 입니다.
아래 그림과 같이 MBR Recored 의 마지막 2byte는 55 AA 로 종료됨을 확인 할 수 있습니다.

000001F0: 00 00 00 00 00 00 00 00 – 00 00 00 00 00 00 55 AA

0x1B8에 위치하는 디스크 시그니쳐는 디스크를 운영체제에 인식 시킵니다. Windows 2000 이상의 운영체제에서 이 시그니쳐를 아래 레지스트리 키의 인덱스로 사용하여 정보를 저장 합니다. (해당 위치를 확인해 보면 c, f 와 같이 설정되어 있거나 아래 레지스트리 키의 index 값을 가집니다.)

HKLM\System\MountedDevices
만약 0x1B8에 위치하는 디스크 시그니처가 A8 E1 B9 D2 (위의 그림에서는 A6 34 1F BA 입니다.)이고 이당 파티션이 Windows 의 논리 드라이버 C를 의미 한다면, HKLM\System\MountedDevices 하위의 \DosDevices\C 값은 아래와 같을 것입니다.

A8 E1 B9 D2 00 7E 00 00 00 00 00 00

첫 번째 4Byte 는 Disk signature 를 말합니다. (실제로는 리틀 엔디언 즉 꺼꾸로 기록되어 있습니다.) 리틀 엔디언 노테이션으로 기록되어 있는 64 bit 값은 파티션의 위치를 나타내는 옵셋으로 사용됩니다. 이 경우 해당 값은 0x7E00 (나머지 숫자는 00 임으로 리틀 엔디언 방식으로 계산 하면 0x7E00 가 됨) 10진수 32,256에 해당하는데 이 값을 섹터의 크기인 512로 나누게 되면 63이 나오고 이를 통해 실제 파티션의 첫 번째 섹터의 위치를 알 수 있습니다. 만약 해당 디스크에 다른 파티션이 있고, 해당 값이 A8 E1 B9 D2 00 F8 93 71 02 00 00 00 이라면 이를 리틀 엔디언 방식으로 치환 하면 0x27193f800 10진수 10,495,457,280 인 것을 알 수 있고 이를 섹터의 크기인 512로 나누게 되면 20,498,940 이 나오게 됩니다. 즉 해당 파티션의 두 번째 논리 디스크는 20,498,940 째 섹터에 위치하게 됩니다.

MBR 및 시그니처를 설명하는데 너무 시간이 길어졌습니다.
자 다시 본론으로 넘어가도록 하겠습니다.

파티션 테이블은 MBR내의 64Byte 의 데이터 구조로 타입과 하드 디스크에서의 위치 정보를 가지고 있습니다. 각 파티션 테이블은 16Byte길이로 (최대 4개의 파티션까지 지원) 각 항목은 아래와 같이 미리 정해진 위치에서 시작 됩니다.
                           Partition 1                       0x1BE   (446 bit)
                           Partition 2                       0x1CE   (462 bit)
                           Partition 3                       0x1DE   (478 bit)
                           Partition 4                       0x1EE    (494 bit)

아래는 MBR의 샘플로 3개의 파티션 테이블이 사용되어 있고 하나가 비어 있는 상태 입니다.
(이 앞 부분은 아시는 것과 같이 실행 코드 및 시그니처 정보가 기입되어 있습니다.)

000001B0:                                                          80 01 (끝 두 자리 입니다.)
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00
00 00
000001D0: 81 0A 07 FE FF FF 8A F5 - 7F 00 3D 26 9C 00
00 00
000001E0: C1 FF 05 FE FF FF C7 1B - 1C 01 D6 96 92 00
00 00
000001F0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00
55 AA

위와 같이 MBR에는 총 4개의 파티션에 대한 설명을 기술할 수 있습니다.
(해당 파티션 정보를 표현하는 값들은 각각 회색 / 검정 / 빨강 / 파랑 으로 표현하였습니다.)

그 첫 번째 필드는 0x1BE 에 위치합니다.
00=부팅에 사용 안됨 80=활성 파티션(부팅에 사용)
아래 그림의 경우 해당 파티션이 활성 파티션이라는 것을 표현하고 있습니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00
00 00

두 번째 값은 0x1BE에 위치하며, 시작 해드를 의미합니다.
아래는 첫 번째 해드를 의미합니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00

세 번째 값은 시작 섹터 및 시작 실린더를 의미 합니다.
다만 아래의 값은 리틀 엔디언 값에 의해 조금 풀어서 확인해야 합니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00

위의 2Byte 값은 아래와 같이 실린더 및 섹터의 값을 의미합니다.
image
(실 비트 9&10 역시 실린더 비트를 의미 합니다. 즉 실린더 비트는 총 10bit 이고 섹터는 6bit를 사용합니다.)
즉 이 경우 해당 값은 0x 00 01 가 되고 이를 풀어서 보면 0000 0000 0000 0001이 되고 이중 0000 0000 00 은 실린더를 00 0001 은 섹터를 의미합니다.

네 번째 값은 시스템 ID를 의미하며 0x07 은 NTPS를 의미합니다.
위치는 0x1C2 입니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00

다음은 시스템 ID 값들입니다.
image
그림의 * 표시는 내결함성이 아니라 스트라이프등을 의미합니다.

FE는 마지막 해드를 의미하며 254번째 해드가 마지막 해드라는 의미 입니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00 

BF 09은 이전과 마찮가지로 마지막 섹터와 마지막 실린더를 나타냅니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00

이 값은 다시 표시하면 0x09BF가 되며 이는 100110111111 이 됩니다.

image

이는 즉 실린더 1001000001 (521)의 섹터 111111 (63)이 마지막 실린더이며 섹터임을 의미합니다.

디스크의 시작 부터 볼륨까지의 섹터 수를 의미하며, 상대 섹터라 부릅니다.
이 경우에는 0x00003F 즉 63번 섹터 부터 시작했음을 확인 할 수 있습니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00

0x1CA 부터 4byte의 값은 전체 섹터의 수를 나타냅니다.
이 경우 0x007FF54B 를 의미하며 이는 8,385,867 개의 섹터를 의미합니다.

000001B0:                                                          80 01
000001C0: 01 00 07 FE BF 09 3F 00 - 00 00 4B F5 7F 00 00 00

이제 Disk이 있는 데이터 구조를 이해하게 되었고 이제는 진행 순서를 알아보고자 합니다. 기억할 것은 POST 가 성공적으로 완료된 이후 과정이라는 것 입니다.

1)  마더보드의 롬 바이오스가 바이오스에 설정되어 있는 첫 부트 디바이스에 접근을 시도 합니다. (일반적으로 사용자가 BIOS 설정 유틸리티를 사용해서 설정 가능합니다.)

2) 롬 바이오스는 첫 번째 부트 디바이스에서 실린더0, 헤드0, 섹터 1를 읽습니다.

3) 롬 바이오스가 한 섹터를 메모리로 읽어 들이고 테스트 합니다.
a. 플로피 드라이브일 경우 첫 번째 섹터는 FAT 부트 섹터 입니다.
b. 하드 드라이브일 경우 첫 번째 섹터는 Master Boot Record(MBR)입니다.

4) 하드 드라이브로 부팅할 경우 롬 바이오스는 섹터 1의 마지막 두 바이트를 확인하여 55AA 인지 확인 합니다.
a. 마지막 두 바이트가 55AA가 아니라면 시스템은 MBR이 손상되었거나 파티션이 만들어지지 않은 것으로 보고 바이오스 인터럽트 18번을 호출하여 바이오스 제작사가 정의한 “Operating System not found” 와 같은 메시지를 출력 합니다.
b. 마지막 두 바이트가 55AA 라면 MBR 프로그램을 실행 합니다.

5) MBR은 파티션 테이블을 검색하여 0x80 즉 부트 파티션인 활성 파티션을 찾습니다.
a. 활성 파티션을 찾을 수 없다면 바이오스 인터럽트 18번을 호출하여 “Operating System not found” 를 출력 합니다.
b. 부트 표지가 0x80이나 0x00이 아니거나 하나 이상의 파티션이 0x80으로 설정이 되어 있는 경우 시스템은 멈추고 “Invalid partition table”를 출력 합니다.
c. 활성 파티션을 찾았다면 찾은 파티션의 부트 섹터를 로드하고 테스트 합니다.

6) MBR은 활성 파티션의 부트섹터를 읽어 들인 후 55AA인지 확인 합니다. (MBR도 부트 섹터의 한 종류입니다. 부트 섹터는 볼륨 부트 레코드를 의미 하며, 이는 파티션의 첫 번째 섹터 로써, 해당 파티션에는 OS가 인스톨 되어 있으며, 기본적으로 OS 로딩 및 호출을 위한 코드를 포함 하고 있습니다. 역시 55 AA 로 끝나는 섹터 입니다.)
a. 부트 섹터를 읽는 것을 5번 실패할 경우 시스템은 실패하고 “Error loading operating system”를 출력합니다.
b. 부트 섹터를 읽었으나 55AA 값이 일치 하지 않는다면 “Missing operating system”를 출력하고 실패 합니다.
c. 부트스트랩 영역은 16섹터로 이루어 집니다.(0-15) 0번째 부트 코드가 올바르나 1-15사이에 손상된 것이 있다면 아무 에러화면 없이 검정 화면을 보게 될 것 입니다. 이 경우 다른 디스크의 1-15섹터(0번 섹터 제외)의 값을 DskProbe로 가져 오면 됩니다.
d. 부트 섹터가 로드 되고 55AA 값이 일치 한다면 MBR은 활성 파티션의 부트 섹터로 제어를 넘깁니다.

7) 활성 파티션의 부트 섹터가 실행되고 NTLDR을 찾습니다. 부트 섹터에 들어 있는 내용은 무엇으로 포멧되었느냐에 따라 달라 집니다. 예를 들어 부프 파티션이 FAT 파티션 이라면 Windows는 부트 섹터를 FAT 파일 시스템을 읽을 수 있도록 작성 합니다. 부트 섹터의 역할은 루트 디렉토리에서 NTLDR을 읽을 수 있도록 논리 드라이브의 포멧과 정보를 제공해 주는 것 입니다. 이 지점에서의 오류는 파일 시스템에 따라 달라 집니다. 아래 FAT 일 경우와 NTFS 일 경우의 에러가 있습니다.
a. FAT : 아래 에러가 발생한 이후 “press any key to restart”가 표시 됩니다.
(1) NTLDR을 찾을 수 없을 경우 “NTLDR is missing”이 표시 됩니다.
(2) NTLDR 이 베드 섹터에 있을 경우 “Disk Error”가 표시 됩니다.
b. NTFS : 아래 에러가 발생한 이후 “Press CTRL+ALT+DEL to restart”가 표시 됩니다.
(1) NTLDR이 베드 섹터에 있을 경우 “A disk read error occurred”가 표시 됩니다. 이 메시지는 Windows 2000또는 이상의 시스템이고 확장 인터럽트 13의 호출이 필요할 경우라면 표시 됩니다. 하지만 CMOS나 SCSI 바이오스에서 표시 됩니다. 이 동작은 FRS(File Record Segment)가 로드 될 수 없거나 NTFS 메타데이타 정보가 손상 되었을 때도 보여 집니다.
(2) NTLDR을 못 찾으면 “NTLDR is missing” 이 표시 됩니다.
(3) NTLDR이 압축 되어 있으면 “NTLDR is compressed”이 표시 됩니다.

9). NTLDR을 찾으면 메모리로 로드 하고 실행 시킵니다. 이 시점에 부트 로더 단계가 시작 됩니다.

|