1. MBR 과 EBR 의 구조에 대한 간략 설명
이번 단락에서 이야기할 MBR 과 EBR, 주 파티션, 확장 파티션, 논리 드라이브에 대한 내용은 이미 다른 글들에서 여러 차례 정리를 했었지만, 이 글만 보실 분들도 계실테니 되집어 보는 의미에서 간단하게 다시 정리하는 시간을 가지도록 하겠습니다.
MBR(Master Boot Record) 은 디스크의 가장 첫 번째 섹터에 위치해 있는 512Byte(섹터 하나의 크기) 공간으로, 이 512Byte 의 작은 공간에 현재 디스크로 부팅할 수 있도록 도와주는 부팅 코드와 함께 디스크 고유의 서명 정보, 그리고 디스크에 포함된 파티션에 대한 정보가 모여 있습니다. 이러한 MBR 을 간략하게 모식으로 나타내면 아래와 같습니다.
코드 영역 : 디스크의 부팅과 관련이 있는 440Byte 의 공간으로 PC 의 부팅과 관련된 작업을 진행합니다. 코드 영역에 기록된 부팅 코드의 기본적인 목적은 파티션 테이블에서 활성 파티션을 찾고 해당 활성 파티션의 부트 섹터로 이동하게끔 해주는 것입니다. [BIOS → MBR 코드 영역 → 활성 파티션의 부트 섹터 → 부트 매니저(로더)]
디스크 서명 : 해당 디스크를 식별하기 위한 4Byte 의 고유한 IDentity 정보입니다. [해당 디스크의 고유한 아이디]
파티션 테이블 : 현재 디스크에 존재하고 있는 파티션에 대한 정보들이 저장된 64Byte 의 공간으로, 파티션의 크기, 위치, 속성, 활성 여부에 대한 정보가 저장되어 있습니다. 파티션 테이블에는 총 네 개의 엔트리(각 16Byte)가 존재하고 있으며, MBR 의 파티션 테이블 엔트리에는 주 파티션과 확장 파티션의 정보가 기록됩니다. 논리 드라이브는 따로 EBR 이라는 공간에 개별적으로 기록됩니다.
디스크 서명 : 해당 디스크를 식별하기 위한 4Byte 의 고유한 IDentity 정보입니다. [해당 디스크의 고유한 아이디]
파티션 테이블 : 현재 디스크에 존재하고 있는 파티션에 대한 정보들이 저장된 64Byte 의 공간으로, 파티션의 크기, 위치, 속성, 활성 여부에 대한 정보가 저장되어 있습니다. 파티션 테이블에는 총 네 개의 엔트리(각 16Byte)가 존재하고 있으며, MBR 의 파티션 테이블 엔트리에는 주 파티션과 확장 파티션의 정보가 기록됩니다. 논리 드라이브는 따로 EBR 이라는 공간에 개별적으로 기록됩니다.
이와 같은 MBR 코드의 전체적인 모습을 실제로 헥스 에디터로 살펴보면 아래와 같습니다.
실제 MBR 의 모습
코드를 실제로 보니까 감이 더 잘 잡히죠? 이제 최종적으로 MBR 의 구조를 표로 정리하면 아래와 같습니다.
주소 | 설명 | 크기 Bytes | |||
---|---|---|---|---|---|
16진수 | 8진수 | 10진수 | |||
0000 |
0000 |
0 | 코드 영역[code area] | 440 (max. 446) | |
01B8 |
0670 |
440 | 디스크 서명[disk signature (optional)] | 4 | |
01BC |
0674 |
444 | 비어 있음[Usually nulls; 0x0000] | 2 | |
01BE |
0676 |
446 | 첫 번째 파티션 엔트리 (16Byte) | 64 | |
두 번째 파티션 엔트리 (16Byte) | |||||
세 번째 파티션 엔트리 (16Byte) | |||||
네 번째 파티션 엔트리 (16Byte) | |||||
01FE |
0776 |
510 | 55h | MBR 서명[MBR signature]; 0xAA55 |
2 |
01FF |
0777 |
511 | AAh | ||
MBR, 전체 크기: 446 + 64 + 2 = | 512 |
다시 기억이 새록새록 떠오르시나요? 아무튼, MBR 은 그 구조적인 문제 때문에 원래는 하나의 디스크에 최대 네 개의 파티션만을 기록할 수 있습니다. 그게 바로 주 파티션(Primary Partition) 입니다. 주 파티션! 기억하시고요.
그런데 이러한 MBR 의 규격대로라면 하나의 디스크에는 최대 네 개의 파티션만을 생성할 수 있습니다. 그런데 솔직히 말해서 네 개는 조금 부족합니다. 그래서 다시 그 안에 파티션을 나눌 수 있는 특수한 파티션을 하나 만들게 됩니다. 그게 바로 확장 파티션(Extended Partition) 입니다. 이러한 확장 파티션은 하나의 디스크에서 하나만 존재할 수 있는 특성이 있습니다. 확장 파티션! 마찬가지로 기억하시고요.
아무튼, 이와 같이 MBR 에는 최대로 [주 파티션 4 개] 또는 [주 파티션 3 개 + 확장 파티션 1 개] 를 기록할 수 있습니다. 파티션에 대한 정보를 담을 수 있는 파티션 엔트리가 네 개 밖에 없으니까요! 매우 간단한 문제잖아요?
자~ 확장 파티션 이야기가 나왔으니 확장 파티션에 대해서 더 이야기를 해야 겠죠? 확장 파티션은 쉽게 그냥 빈 껍데기 파티션이라고 생각하시면 됩니다. 이 안에 (주 파티션과는 다른) 새로운 파티션을 생성할 수 있다고 영역만 그어 놓은 파티션인 겁니다. 그리고 이렇게 확장 파티션 안에 생성할 수 있는 파티션을 논리 드라이브(Logical Drive)라고 부릅니다.
그런데 논리 드라이브도 파티션이니까 그 정보를 기록해야 겠죠? 하지만 MBR 의 파티션 테이블 엔트리는 주 파티션과 확장 파티션에서 모두 사용했기 때문에(사용할 것이기 때문에) 그곳에 논리 드라이브의 정보를 기록할 수는 없습니다. 그래서 확장 파티션내에 EBR(Extended Boot Record) 라는 것을 두고 논리 드라이브에 대한 정보는 그곳에 따로 기록을 하는 방식을 사용하게 됩니다. 즉, 논리 드라이브는 주 파티션이나 확장 파티션과는 다르게 MBR 에 정보가 기록되는 게 아니라, EBR 이라는 독립된 공간에 따로 기록이 되는 거죠.
이러한 EBR 의 기본적인 구조 자체는 MBR 과 100% 똑같습니다. 단지 코드 영역과 같은 부분들은 필요가 없기 때문에 사용되지 않고, 파티션 테이블 엔트리 부분만 사용할 뿐이죠. 그런데 MBR 의 파티션 테이블 엔트리가 총 네 개 뿐인지라 최대 네 개의 파티션만 생성할 수 있다는 제한이 생겼고, 그로 인해 확장 파티션과 논리 드라이브란 것을 추가로 만들었습니다.
자~ 그럼 여기에서 생각을 해보도록 하겠습니다. 기본적으로 EBR 도 MBR 과 그 구조가 100% 똑같다고 했습니다. 만약 EBR 의 파티션 엔트리를 MBR 과 동일한 방식으로 사용한다면 어떻게 될까요? 마찬가지로 확장 파티션 내에 생성 가능한 논리 드라이브의 개수도 최대 네 개라는 똑같은 제한이 생기겠죠. 기껏 힘들게 확장 파티션과 논리 드라이브라는 개념을 만들어서 파티션 개수의 한계를 극복해보고자 하는데 이러면 또 별로 재미가 없잖아요?
그래서 EBR 은 MBR 과는 다른 방식으로 파티션 엔트리를 사용합니다. 우선 EBR 은 MBR 처럼 하나만 존재하는 게 아닙니다. 논리 드라이브가 생성될 때 함께 생성이 되는 방식입니다. 즉, EBR 은 논리 드라이브의 개수 만큼 존재하게 됩니다. 이러한 상태에서 첫 번째 파티션 엔트리에는 현재 자신과 연결된 논리 드라이브에 대한 정보를 기록하고, 두 번째 파티션 엔트리에는 다음 EBR 의 위치를 기록하는 방식을 사용합니다.
즉, 정리하면 EBR 은 MBR 과 달리 하나만 있는 게 아니라 논리 드라이브의 개수만큼 EBR 이 생성되는 것이고, 앞서의 EBR 에서 다음 EBR 의 위치를 알려주는 방식을 사용합니다. 이처럼 EBR 은 체인과 같이 서로 끊임없이 연결될 수 있고, 이러한 구조로 논리 드라이브는 개수의 제한 없이 원한다면 계속하여 생성할 수 있습니다.
EBR 의 구조
[출처 - 마이크로소프트 테크넷]
[출처 - 마이크로소프트 테크넷]
이 때 EBR 은 논리 드라이브가 생성될 때 함께 생성이 되기 때문에, 마이크로소프트 테크넷의 자료처럼 EBR 을 그냥 논리 드라이브에 포함된 하나의 구조로 보기도 합니다. 뭐 이건 쉬운 이해를 위해 구조를 어떻게 바라 보느냐 하는 시선의 문제이기 때문에 깊게 생각할 문제는 아니고요. 그저 기본적인 구조는 MBR 과 동일하지만 파티션 테이블 엔트리를 사용하는 방법이 다르다는 것, 하나만 존재하는것이 아닌 논리 드라이브 개수만큼 함께 생성된다는 것, EBR 끼리 서로 연결되는 방식으로 무한히 확장된다는 것, 이 세 가지만 기억하시면 될 듯 합니다.
여기까지가 MBR 과 EBR 의 파티션 테이블 엔트리 정보를 해석하기 위해 기본적으로 알고 있어야 할 내용입니다. 예전에 정리를 끝냈지만 이 글만 보실 분들도 계실 것이기 때문에 다시 한 번 간략하게 정리를 해보았습니다. 그럼 본격적으로 MBR 과 EBR 의 파티션 테이블 엔트리 정보를 어떻게 해석할 것인지, 그것에 대해서 이야기를 해보도록 하겠습니다.
2. MBR 에 위치한 주 파티션에 대한 파티션 테이블 엔트리 정보의 해석
총 6 개의 파티션으로 구성된 예제 디스크
[주 파티션 2 개 + 확장 파티션 1 개 + 논리 드라이브 3 개]
[주 파티션 2 개 + 확장 파티션 1 개 + 논리 드라이브 3 개]
위와 같은 예제 디스크를 준비해봤습니다. 현재 예제 디스크는 총 6 개의 파티션으로 구성이 되어 있죠. 이 중에 주 파티션과 확장 파티션에 대한 정보는 MBR 의 파티션 테이블 엔트리에 기록이 되어 있을 것이며, 세 개의 논리 드라이브에 대한 정보는 함께 생성된 각각의 EBR 에 기록되어 있을 겁니다.
아래는 실제로 위 디스크의 MBR 정보를 헥스 에디터를 통해 살펴본 것입니다. 주 파티션 2 개와 확장 파티션 1 개, 총 세 개의 파티션에 대한 정보가 기록되어 있는 것을 실제로 확인할 수 있습니다.
총 네 개의 파티션 테이블 엔트리 중 3 개의 파티션 테이블 엔트리에 정보가 기록되어 있는 모습.
위의 헥스 에디터를 통해 살펴본 파티션 테이블 엔트리에 기록된 정보를 보기 편하게 다시 글로 정리하면 아래와 같습니다.
첫 번째 파티션 엔트리 정보 | 80 20 21 00 07 FE FF FF 00 08 00 00 00 00 00 05 | ||
---|---|---|---|
두 번째 파티션 엔트리 정보 | 00 FE FF FF 07 FE FF FF 00 08 00 05 00 00 C0 03 | ||
세 번째 파티션 엔트리 정보 | 00 FE FF FF 0F FE FF FF 00 08 C0 08 00 A0 27 06 |
최종적으로 이 정보를 해석하기 위해 필요한 파티션 테이블 엔트리의 구조는 아래와 같습니다. 해당 구조에 맞춰서 각 파티션 테이블 엔트리의 정보를 해석하기만 하면 되는 거죠.
오프셋 | 필드 길이 | 설명 |
---|---|---|
0x00 | 1 Byte | 파티션 상태 (0x80 = 부팅 가능, 0x00 = 부팅 불가, 기타 = 비정상) |
0x01 | 3 Byte | 파티션의 첫 번째 섹터의 실린더-헤드-섹터 주소 [CHS 주소] |
0x04 | 1 Byte | 파티션의 종류(형식) |
0x05 | 3 Byte | 파티션의 마지막 섹터의 실린더-헤드-섹터 주소 [CHS 주소] |
0x08 | 4 Byte | 파티션의 첫 번째 섹터의 LBA 주소 |
0x0C | 4 Byte | 파티션의 크기 (단위: 섹터) [* 전체 섹터의 개수] |
여기에서 한 가지 중요한 것은 파티션 테이블 엔트리의 모든 정보는 리틀 엔디안 방식으로 저장이 되어 있다는 것입니다. 그렇기 때문에 정보를 해석할 때도 리틀 엔디안 방식으로 해석을 해야 합니다. 리틀 엔디안과 빅 엔디안이 무엇인지는 각자 알아서 찾아보시도록 하고요. 이 글에서는 따로 설명하지 않도록 하겠습니다.
그럼 글에서는 첫 번째 파티션 테이블 엔트리에 저장되어 있는 첫 번째 주 파티션에 대한 정보를 해석해보도록 하겠습니다.
첫 번째 파티션 엔트리 정보 | 80 20 21 00 07 FE FF FF 00 08 00 00 00 00 00 05 |
---|
A. 파티션 상태
오프셋 | 필드 길이 | 설명 |
---|---|---|
0x00 | 1 Byte | 파티션 상태 (0x80 = 부팅 가능, 0x00 = 부팅 불가, 기타 = 비정상) |
첫 번째 파티션 엔트리 정보 | 80 20 21 00 07 FE FF FF 00 08 00 00 00 00 00 05 |
---|
해당 파티션이 활성 파티션인지 아닌지를 나타내는 값입니다. 즉, 현재 80 이기 때문에 이 파티션은 부팅할 수 있는 활성 파티션이라는 의미가 됩니다. 만약 일반 파티션이라면 00 의 값을 가지게 됩니다. 간단하죠? 이것에 대해선 더 이야기할 게 없네요.
B. 파티션의 종류
오프셋 | 필드 길이 | 설명 |
---|---|---|
0x04 | 1 Byte | 파티션 종류 |
첫 번째 파티션 엔트리 정보 | 80 20 21 00 07 FE FF FF 00 08 00 00 00 00 00 05 |
---|
해당 파티션의 형식(종류)가 무엇인지를 나타내줍니다. 현재 07 값을 가지고 있기 때문에 해당 파티션이 NTFS 파일 시스템이거나 exFAT 파일 시스템일 것이라고 예상할 수 있습니다. 만약에 이 값이 0F 의 값을 가지고 있다면, 해당 파티션은 확장 파티션임을 의미하게 됩니다. 파티션 형식 값에 대한 보다 자세한 정보는 아래의 글들을 참고하시길 바랍니다.
C. 파티션의 시작 위치와 마지막 위치 - CHS 주소 체계
오프셋 | 필드 길이 | 설명 |
---|---|---|
0x01 | 3 Byte | 파티션의 첫 번째 섹터의 실린더-헤드-섹터 주소 [CHS 주소] |
0x04 | 1 Byte | 파티션 종류 |
0x05 | 3 Byte | 파티션의 마지막 섹터의 실린더-헤드-섹터 주소 [CHS 주소] |
첫 번째 파티션 엔트리 정보 | 80 20 21 00 07 FE FF FF 00 08 00 00 00 00 00 05 |
---|
디스크의 처음을 기준으로 파티션이 시작되는 위치와 마지막 끝나는 위치를 CHS 주소 체계로 표현한 값입니다. 즉, 해당 파티션이 정확하게 디스크의 어디부터 어디까지 위치해 있는지 그 영역을 알려주는 정보이죠. 하지만 미리 결론을 말하자면 이 정보는 현재는 실질적으로 그 역할을 제대로 수행하지 못하는 죽은 정보입니다. 이유는 간단합니다. 이미 현대 디스크의 용량이 24bit(3Byte) 의 CHS 주소 체계로 표현할 수 있는 한계를 벗어났기 때문입니다.
그래도 일단 해석은 해보죠. 파티션 테이블 엔트리에서 CHS 주소는 [실린더 10bit, 헤드 8비트, 섹터 6bit] 해서 총 24bit(3Byte) 의 값으로 기록이 되어 있습니다. 그런데 이게 좀 많이 복잡하게 되어 있습니다. 우선 현재 첫 번째 파티션 테이블 엔트리의 파티션 시작 위치 정보인 20 21 00 값을 해석하려면 아래와 같은 구조로 해석하면 됩니다.
20 | 21 | 00 | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ||
↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ||
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ||
헤드(Head) | 실(C) | 섹터(Sector) | 실린더(Cylinder) |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
어째 예제가 별로 좋지 못한 기분이 들지만 아무튼, 실린더 10bit, 섹터가 6비트, 헤드가 8비트이기 때문에 파티션 엔트리에 저장되어 있는 헥스 값을 비트 값으로 변환하여 풀어헤치고, 이를 다시 위의 구조에 대입하여 각 값을 알아낸 후, 최종적으로 데시멀 값으로 변환하여 CHS 주소 값을 알아내면 됩니다. 이 때 실린더 10bit 값을 조합할 때는 예제에서 21 값의 00 을 값의 가장 앞으로 붙이면 됩니다. [이게 지금 예제가 별로라 좀 헷갈리는데 마지막에 간단하게 다른 예제로 설명을 하도록 하겠습니다.]
아무튼, 현재 나온 CHS 주소의 값을 십진수 값으로 변환하면 CHS 0:32:33 이라는 주소를 최종적으로 얻을 수 있습니다.
하지만 파티션 테이블 엔트리에서 사용하는 총 24bit 의 CHS 주소 체계로 표현 가능한 용량은 2^10 x 2^8 x (2^6 - 1) x 512Byte = 7.88GB 라는 한계를 가지고 있습니다. 즉, 최대 실린더 수 1024(0~1,023), 최대 헤드 수 256(0~255), 최대 섹터 수 63(1~63) 이라는 주소 표현 한계가 존재하기 때문에 디스크에서 7.88GB 를 넘어서는 지점 부터는 파티션 테이블 엔트리에서 CHS 주소로는 표현이 불가능한 것이죠.
그래서 실제로 예제로 살펴 보고 있는 파티션 엔트리에 기록된 해당 파티션의 마지막 섹터 위치인 FE FF FF 값을 해석하게 되면, 십진수 값으로 CHS 1023:254:63 이라는 거의 최대 한계에 근접한 값이 나오게 됩니다.
FE | FF | FF | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | ||
↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ||
1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | ||
헤드(Head)) | 실(C) | 섹터(Sector) | 실린더(Cylinder) |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 |
이로 인해 실제로는 40GB 짜리 파티션인데 파티션의 마지막 위치는 대략 7.84GB 지점이라는 어처구니 없는 결과가 나오게 됩니다. 이게 바로 제가 처음에 실질적으로 그 역할을 제대로 수행하지 못하는 죽은 정보라고 표현한 이유입니다. 물론 만약에 파티션의 시작 위치와 끝나는 위치가 모두 디스크의 7.84GB 안 지점에 존재한다면 이러한 CHS 주소 값으로도 해당 파티션의 위치를 파악할 수 있습니다. 하지만 현재의 컴퓨팅 환경에선 사실상 그러한 경우가 드물기 때문에 결론적으로 현대에 와서는 이러한 파티션 엔트리의 CHS 주소 값들은 실제로는 사용되지 않는 죽은 값이 되었다고 보아도 좋은 것입니다.
그래서 같은 이유로 파티션 엔트리를 잘 살펴보면 대부분의 파티션 엔트리에서 파티션의 시작 위치와 마지막 위치를 나타내는 CHS 주소 값이 한계 값인 FE FF FF 값을 가지고 있는 것을 확인할 수 있습니다. 말한 것과 같이 디스크의 7.84GB 를 넘어서는 지점은 CHS 주소로 표현할 수 없기 때문에 발생하게 되는 현상입니다.
사실상 현대의 디스크에서 CHS 주소 체계는 명맥만 남았다고 보셔도 좋습니다. 이제는 LBA 주소 체계가 사용되고 있고, 파티션 엔트리에서도 파티션의 시작 위치와 마지막 위치를 파악하는데에도 바로 뒤에서 알아 볼 LBA 주소 정보를 대신 사용하게 됩니다.
여담이지만 CHS 주소 체계는 디스크의 기본 주소 지정 체계가 LBA 주소 체계로 전환되면서 사라졌어야 했지만, 기존의 CHS 주소 체계를 사용하던 프로그램들과의 호환성을 위해 어쩔 수 없이 그 구조만이 남아서 현재까지 오고 있는 것입니다. 그래서 현재 사용되는 CHS 주소 체계는 실린더당 헤드의 개수 값은 255 로, 트랙당 섹터의 개수 값은 63 으로 고정한 채 실린더의 값을 한없이 늘린 형태로 사용하고 있습니다.
참고로 CHS 주소를 LBA 주소로 변환하는 방법은 아래와 같습니다.
LBA = ((실린더 값 x 실린더당 헤드 개수 + 헤드 값) x 트랙당 섹터 개수) + 섹터 값 - 1
말한 것과 같이 현재의 CHS 주소 체계는 실린더 당 헤드의 개수는 255 개로, 트랙당 섹터의 개수는 63 개로 고정한채 실린더 값을 계속하여 늘린 형태이기 때문에 위에서 살펴본 첫 번째 파티션 엔트리의 파티션 시작 위치인 CHS 0:32:33 주소를 LBA 주소로 변환하면 ((0 x 255 + 32) x 63 ) + 33 - 1 = 2,048 하여 LBA 2,048 값이 나오게 됩니다. 참고로 알아두시길 바랍니다.
※ 파티션 엔트리의 CHS 주소 파악하기 다른 예제
* 파티션의 시작 위치 (CHS 주소) :: 실린더 1000001010 : 헤드 01001011 : 섹터 000010 → CHS 522:75:2
CHS to LBA 변환 :: ((실린더 값 x 실린더당 헤드 개수 + 헤드 값) x 트랙당 섹터 개수) + 섹터 값 - 1
((522 x 255 + 75) x 63 ) + 2 - 1 = 8,390,656
* 파티션의 시작 위치 (LBA 주소) :: 00 08 80 00 → 00 80 08 00 → Hex 800800 → Dec 8,390,656
* CHS 주소 정보를 통해 변환한 LBA 값과 LBA 주소 정보의 값이 일치하는 것을 확인.
파티션 엔트리 정보 | 00 4B 82 0A 07 D5 89 8C 00 08 80 00 00 00 20 00 |
---|
4B | 82 | 0A | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | ||
↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ||
0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | ||
헤드(Head)) | 실(C) | 섹터(Sector) | 실린더(Cylinder) |
1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
* 파티션의 시작 위치 (CHS 주소) :: 실린더 1000001010 : 헤드 01001011 : 섹터 000010 → CHS 522:75:2
CHS to LBA 변환 :: ((실린더 값 x 실린더당 헤드 개수 + 헤드 값) x 트랙당 섹터 개수) + 섹터 값 - 1
((522 x 255 + 75) x 63 ) + 2 - 1 = 8,390,656
* 파티션의 시작 위치 (LBA 주소) :: 00 08 80 00 → 00 80 08 00 → Hex 800800 → Dec 8,390,656
* CHS 주소 정보를 통해 변환한 LBA 값과 LBA 주소 정보의 값이 일치하는 것을 확인.
D. 파티션의 시작 위치 - LBA 주소 체계
오프셋 | 필드 길이 | 설명 |
---|---|---|
0x08 | 4 Byte | 파티션의 첫 번째 섹터의 LBA 주소 |
첫 번째 파티션 엔트리 정보 | 80 20 21 00 07 FE FF FF 00 08 00 00 00 00 00 05 |
---|
디스크의 처음을 기준으로 파티션이 시작되는 위치를 LBA 주소 체계로 표현한 값입니다. 즉, 앞서의 CHS 주소 정보 때와 마찬가지로 해당 파티션의 영역이 정확하게 디스크의 어느 지점에서 시작하는지를 알려주는 정보이죠. 그런데 LBA 주소 정보에서는 앞서 살펴본 CHS 주소 정보와는 다르게 오직 파티션이 시작하는 위치만을 알려주는데요. 이는 파티션의 시작 위치를 알고 파티션의 정확한 크기를 알면 파티션이 끝나는 지점은 간단하게 계산할 수 있기 때문에, 굳이 파티션이 끝나는 지점까지 LBA 주소로 표현할 필요는 없다고 판단한 모양입니다. [아니 그럼 CHS 주소 정보도 그런 식으로 했으면 되잖아? 라고 물어 보실 분들! 이런 자료를 해석할 때마다 항상 하는 말이지만, 이거 제가 설계한 거 아닙니다. 그러니 저에게 딴지 걸지 마세요. 전 다른 놈들이 십수년 전에 이미 만들어 놓은 것을, 단순히 해석하는 위치에 있을 뿐입니다.]
LBA 주소는 CHS 주소처럼 복잡한 구조를 가지고 있지 않고, 논리적으로 모든 섹터를 일렬로 정렬시켜놓고 차례로 번호를 매긴 매우 간단한 주소 체계이기 때문에, 파티션 엔트리에 저장되어 있는 00 08 00 00 값을 그대로 해석하면 됩니다.
해당 값은 리틀 엔디안 방식이기 때문에 역순으로 읽으면 됩니다. 즉, 00 00 08 00 값이 그대로 LBA 주소가 되는 것이죠. 앞의 0 값들은 빈 값이기 때문에 떼어버리면 800 이라는 헥스 값만 남죠. 이를 십진수 값으로 변환하게 되면 LBA 2,048 값이 나오게 됩니다.
즉, 해당 파티션은 2,048 번째 섹터에서 시작하는 것이고, 이를 용량 단위로 해석하면 섹터 하나의 크기는 512Byte 이기 때문에 해당 파티션은 디스크의 2,048 x 512Byte = 1MB 지점에서 시작하는 게 되는 것이죠. 프로그램에 따라서 '파티션의 시작 섹터가 2,048 섹터이다.' 또는 '파티션의 오프셋은 1MB 지점이다.' 라고 달리 표현하기도 합니다. 그냥 참고로 알아 두시고요.
아래는 이렇게 구한 LBA 2,048 (Logical Sector 2,048) 지점을 실제로 헥스 에디터를 통해 살펴본 모습입니다. 부트 섹터(NTFS 파티션이기 때문에 정확하게는 VBR) 의 모습이 보이네요. 이를 통해 파악한 파티션의 시작 지점이 정확한 것을 확인할 수 있습니다.
파티션의 시작 지점에 정확하게 위치해있는 부트 섹터(VBR)의 모습
E. 파티션의 크기 - 파티션에 포함된 전체 섹터의 개수
오프셋 | 필드 길이 | 설명 |
---|---|---|
0x0C | 4 Byte | 파티션의 크기 (단위: 섹터) [* 전체 섹터의 개수] |
첫 번째 파티션 엔트리 정보 | 80 20 21 00 07 FE FF FF 00 08 00 00 00 00 00 05 |
---|
마지막으로 해당 파티션이 총 몇 개의 섹터로 이루어져 있는지 파티션에 포함된 전체 섹터의 개수를 표현한 정보입니다. 이를 통해 해당 파티션의 정확한 크기를 파악할 수 있습니다. 단순한 개수 정보이기 때문에 간단하게 00 00 00 05 라는 값 자체를 해석하면 그게 그대로 섹터의 개수가 됩니다.
역시나 리틀 엔디안 방식이기 때문에 해석할 땐 역순인 05 00 00 00 으로 파악하면 됩니다. 헥스 값 5,000,000 을 그대로 십진수 값으로 변환하면 83,886,080 개가 됩니다. 즉, 해당 파티션은 총 83,886,080 개의 섹터로 이루어져 있는 것이죠. 섹터 하나의 용량은 512Byte 이기 때문에, 이를 계산하면 [83,886,080 x 512Byte = 42,949,672,960Byte = 41,943,040KB = 40,960MB = 40GB] 가 되죠. 즉, 해당 파티션의 크기는 40GB 인 것을 알 수 있습니다. 간단하죠?
이제 여기에서 덤으로 앞서 구한 파티션의 시작 위치에 이곳에서 구한 전체 섹터의 개수를 더한 후 1 을 빼면 파티션의 마지막 지점에 대한 섹터 위치도 파악이 가능합니다. 즉, 2,048 + 83,886,080 - 1 = LBA 83,888,127 지점이 바로 해당 파티션이 끝나는 위치인 것이죠. 간단하죠?
3. MBR 에 위치한 확장 파티션 정보를 통해 EBR 의 위치를 파악하고 해석하기
이번엔 논리 드라이브에 대한 정보가 담겨 있는 EBR 을 살펴보도록 하겠습니다. 먼저 알아두셔야 할 것은 EBR 정보는 MBR 에 기록된 확장 파티션에 대한 정보와 함께 봐야 한다는 겁니다. 예제에서 확장 파티션은 MBR 의 세 번째 파티션 엔트리에 기록되어 있었습니다. 이 때 모든 정보의 해석은 주 파티션 때와 동일하게 해석하시면 됩니다.
세 번째 파티션 엔트리 정보 | 00 FE FF FF 0F FE FF FF 00 08 C0 08 00 A0 27 06 |
---|
확장 파티션의 시작 지점은 00 08 C0 08 이죠. 해당 지점을 찾으면 바로 그곳에 첫 번째 EBR 이 있습니다. 마찬가지로 리틀 엔디안 방식이기 때문에 역순으로 읽으면 08 C0 08 00 이 됩니다. 이를 십진수 값으로 변환하면 LBA 146,802,688 값이 나오죠. 해당 지점이 바로 확장 파티션이 시작되는 지점이고, 그곳에 바로 첫 번째 EBR 이 위치하고 있습니다.
확장 파티션의 시작 지점에 정확하게 위치해있는 EBR 의 모습.
EBR 에선 첫 번째 파티션 엔트리와 두 번째 파티션 엔트리만이 사용되기 때문에 굉장히 휑하죠? 여기에서 첫 번째 파티션 엔트리의 정보는 바로 해당 EBR 과 연결된 논리 드라이브에 대한 정보(Current Entry)이고, 두 번째 파티션 엔트리의 정보는 다음 EBR 의 위치를 나타내는 정보(Next Entry)입니다.
그런데 이러한 EBR 의 정보를 해석할 때에는 미리 알아두셔야 할 굉장히 중요한 내용이 있습니다.
1. Current 엔트리에서 LBA 시작 위치는 현재 자기 자신(EBR)의 위치를 기준으로 합니다. 나머지는 MBR 때와 동일합니다.
2. Next 엔트리에서 다음 EBR 의 위치는 확장 파티션의 시작 위치를 기준으로 합니다.
2. Next 엔트리에서 다음 EBR 의 위치는 확장 파티션의 시작 위치를 기준으로 합니다.
현재 첫 번째 EBR 에서 Current 와 Next 엔트리의 정보는 아래와 같습니다.
Current 엔트리 정보 | 00 FE FF FF 07 FE FF FF 00 08 00 00 00 00 80 02 | ||
---|---|---|---|
Next 엔트리 정보 | 00 FE FF FF 05 FE FF FF 00 08 80 02 00 08 40 01 |
자~ Current 엔트리에서 현재 EBR 과 연결된 논리 드라이브의 시작 위치는 00 08 00 00 라고 나오네요. 리틀 엔디안 방식으로 해석하면 00 00 80 00 해서 헥스 값으로 800 이 나오고, 이를 십진수 값으로 변환하면 2,048 이 됩니다. 그런데 이는 현재 EBR 의 위치, 즉 자기 자신의 위치를 기준으로 한 위치라고 했죠?
그래서 최종적으로 첫 번째 논리 드라이브의 시작 위치는 현재 EBR 의 위치 값에 이렇게 나온 값을 더해주어야 합니다. 현재 EBR 은 첫 번째 EBR 이기 때문에 확장 파티션의 시작 위치와 동일합니다. 그래서 최종적으로 아래와 같이 나오게 됩니다.
146,802,688 + 2,048 = LBA 146,804,736
첫 번째 논리 드라이브의 시작 지점(부트 섹터, VBR) 모습
이제 파티션의 종류라던가, 파티션의 크기와 같은 Current 엔트리에서 나머지 정보는 MBR 때와 동일하게 해석하시면 됩니다.
다음으로 Next 엔트리에 기록되어 있는 두 번째 EBR 의 위치는 00 08 80 02 이죠. 리틀 엔디안 방식으로 해석하면 02 80 08 00 해서 최종적인 십진수 값으로는 41,945,088 이 됩니다. 그런데 이 값은 확장 파티션의 시작 위치를 기준으로 한다고 했습니다. 그래서 확장 파티션의 시작 위치 값에 이 값을 더해주면 다음 EBR 의 위치를 파악할 수 있습니다.
146,802,688 + 41,945,088 = LBA 188,747,776
두 번째 EBR 의 모습
그러면 위와 같이 두 번째 논리 드라이브에 대한 정보가 담겨 있는 두 번째 EBR 의 모습을 확인할 수 있습니다. 이제 두 번째 EBR 의 Current 와 Next 엔트리 정보를 확인해보면 아래와 같습니다.
Current 엔트리 정보 | 00 FE FF FF 07 FE FF FF 00 08 00 00 00 00 40 01 | ||
---|---|---|---|
Next 엔트리 정보 | 00 FE FF FF 05 FE FF FF 00 10 C0 03 00 08 40 01 |
역시나 또 계산을 해보도록 하겠습니다. 두 번째 논리 드라이브의 시작 위치인 00 08 00 00 정보는 다시 한 번 말하지만 현재 EBR 의 위치를 기준으로 한다고 했습니다. 아무튼, 00 00 08 00 으로 해석하여 십진수 값으로 변환하면 2,048 이고, 여기에 현재 EBR 의 위치를 더해주면 되는 것이죠.
188,747,776 + 2,048 = LBA 188,749,824
두 번째 논리 드라이브의 시작 지점(부트 섹터, VBR) 모습
다음으로 Next 엔트리에 기록되어 있는 세 번째 EBR 의 위치는 00 10 C0 03 값을 가지고 있습니다. 03 C0 10 00 으로 해석하여 십진수 값으로 변환하면 62,918,656 이 나옵니다. 반복하여 계속 말하게 되지만 Next 엔트리의 다음 EBR 위치는 확장 파티션의 시작 지점을 기준으로 한다고 했습니다. 그래서 확장 파티션의 시작 위치 값에 현재 구한 값을 더해주면 세 번째 EBR 의 위치가 나오게 됩니다.
146,802,688 + 62,918,656 = LBA 209,721,344
세 번째(마지막) EBR 의 모습
좀 헷갈리지만 잘 생각해보면 그래도 간단하죠? 이제 이렇게 확인한 세 번째 EBR 은 마지막 EBR 이기 때문에 Current 엔트리는 정보가 있지만, Next 엔트리는 비어 있는 것을 확인할 수 있습니다. 만약 이 상태에서 네 번째 논리 드라이브를 생성한다면 동시에 네 번째 EBR 이 생성되며, 바로 이 EBR 의 Next 엔트리에도 다음 네 번째 EBR 의 위치가 기록되는 겁니다.
이와 같은 방식으로 EBR 은 이전 EBR 정보와 연계되어 계속 새롭게 생성되는 방식으로 운영되기 때문에, 논리 드라이브의 생성 개수는 이론적으로 무한히 생성될 수 있는 것입니다. EBR 의 정보 해석에 대해서는 이정도면 될 듯 합니다.
4. 마치며...
현재 글에서 사용한 디스크의 정보를 확인할 수 있는 헥스 에디터는 아래의 무료 헥스 에디터 프로그램을 사용하였습니다.
그리고 Hexadecimal - Decimal - Octadecimal - Binary 값의 변환에는 작고 가벼운 아래의 프로그램을 추천합니다. 참고로 헥스 값을 변환할 때에는 대소문자를 주의하시길 바라며, 값을 입력하실 때에는 소문자로 입력하시면 됩니다.
그럼 도움이 되셨길 바라며, 이번 글은 여기까지 하도록 하겠습니다. 이상입니다. ^^