MBR이라는 것은 Master Boot Record 의 약자로, 바로바로 컴퓨터 부팅과 매우 밀접한 관계를 갖고있다. 참 이것을 설명하려면 추가적으로 설명해야하는 지식이 많은데, 다 설명을 해야할까 하는 고민을 했었다. 하지만 이것에 대해 깊게 이해하려면 어느정도의 배경 지식은 필요하다는 생각이 들어 한번 전체적인 배경지식을 쭉 설명해 보겠다.
1. 컴퓨터의 발전..
자 여러분들은 컴퓨터 부팅이 어떻게 이루어지는지 아는가?
오늘날 컴퓨터는 우리 일상생활에 뗄레야 뗄 수가 없는 말 그대로 우리 삶을 좌우하는 장치라고 봐도 과언이 아닐 것이다. 랩톱, 태블릿, 노트북, 워치, 티비, 냉장고, 서버, NAS 등 평소에 별 생각이 없다가도 얼마나. 많은 컴퓨터 장치들이 우리 삶과 연결되어있는지를 떠올려보면 놀랍기까지 하다.
최초 컴퓨터는 천공관에서 시작했다. 천공관이라는 소자를 사용해 로직을 구현한것으로 부터 시작해 트랜지스터의 발명으로 이어졌고, 이는 곧 집적(integration)으로 이어져 오늘날의 고성능 컴퓨터가 되었다. 옛날의 컴퓨터는 사실 꽤나 불편하고도 전문적인 장치였다. 사람과 상호작용할 수 있는 인터페이스를 갖추고는 있었지만, 컴퓨터를 잘 모르는 사람들이 본다면 지레 겁을 먹는 일명 "도스 화면" 이라고 하는 시꺼먼 CLI환경만이 제공되었으니 말이다.
이후 컴퓨터 성능이 비약적으로 개선되며 점점 전문적인 지식이 없는 사용자도 사용이 편리하도록 GUI라는 상호작용 환경이 탄생했다. 그러면서 차츰 전문적인 지식이 없어도 사용자가 필요한 기능을 충분히 제공하고 또 이를 활용할 수 있는 생태계가 구성되었다.
2. 컴퓨터의 부팅
자 이런 발전 과정을 거쳐오면서 우리 눈에 보이지 않는 어떤 로직들이 컴퓨터를 이렇게 동작하도록 해주는지 우리는 아무런 관심이 없어도 컴퓨터를 사용하는데 아무런 문제가 없었다. 하지만 잘 알아도 나쁠건 없을것이다. 특히 필자는 정말 그 모든과정이 너무나도 궁금했다. 이번 단락에서는 그러한 과정들을 한번 설명해보고자 한다.
컴퓨터 조립에 관심이있는 독자라면 한번쯤 컴퓨터 전원을 드라이버로 켜본적이 있을 것이다. 이것이 무슨 말인가 하면, 우리가 보통 컴퓨터를 켤때 어떻게 하는가? 이게 질문거리가 되는건가 싶은 질문이다. 전원 버튼을 눌러 켜지 않겠는가? 바로 그렇다. 그럼 이전원 버튼을 누른다는 행위는 어떤 현상을 만들어내는가? 바로 '쇼트' 를 만들어낸다.
전기에 대해 잘 모르는 사람들도 이 '쇼트'라는 단어를 들어보았을 것이다. 쇼트는 단락 한국어로 '단락' 이라는 뜻인데 쉽게 얘기하자면떨어져있던 회로가 연결되어 전기가 흐르는 현상을 말한다. 만약 우리가 의도하지 않은 쇼트였다면 회로 또는 퓨즈가 타버리는 트러블을 만들어낼 수도 있지만 우리가 원하는 대로 만들어 유용하게 사용할 수도 있을 것이다. 바로 전원버튼과 같은 '스위치' 기능을 만드는 것이다.
자 전원 버튼을 누름으로써 쇼트가 발생하고, 이로써 이제 전원을 on 하겠다는 신호가 회로로 전해진 것이다. 그뒤에는 어떻게 될까?
바이오스 또는 "BIOS" 라는 단어를 들어보았을 것이다. 원래는 Basic Input Output System의 약자인데 거의 고유명사가 되어버린 그런 단어다. 이 바이오스는 물리적인 장치와 소프트웨어 사이의 연결을 담당한다. 컴퓨터에서 다음과 같은 화면들을 본 적이 있을 것이다.
이는 BIOS의 ROM에 저장된 프로그램으로, CMOS라는 IC의 설정값을 변경할 수 있게 도와주는 인터페이스다.
자 한번 생각해보자. 우리가 컴퓨터와 상호작용(interaction) 하려면 어떤 방법을 사용하는가? 키보드와 마우스 또는 터치등의 장치를 사용한다. 그럼 컴퓨터는 어떻게 이런 장치들이 자신들에게 명령을 내린다고 인지할 수 있을까? 바로 BIOS가 중간에서 이런 동작들을 도와주는 것이다.
잠시 샛길로 빠졌는데, 전원 신호가 인가된 후 BIOS의 ROM(Read Only Memory)은 메모리에 적재되고 이 BIOS 프로그램이 입출력장치와 여러가지 CPU, 메모리 등을 초기화하는 역할을 수행한다. 이후 보조 저장장치에 기록된 MBR이라는 것을 읽어 메모리에 적재한다. 이후 MBR의 부트 코드가 실행되면서 부팅이 시작된다.
자 여기서도 잠시 샛길로 빠져보자면.. 여러분은 프로세스와 파일의 차이를 알고 있는가? 프로세스와 파일의 본질적인 차이는 무엇이란 말인가. 파일이 실행되려면 어떤 과정을 거쳐야하는가 하는 것들을 한번 생각해보면 좋겠다.
3. MBR(Master Boot Recoed) 이란?
아무튼 그래서 드디어 이 MBR이라는것이 등장한다. 이 MBR이라는 것은 어떤 물리저장장치의 첫 섹터(512Bytes, 0x200Bytes)에는 무조건 존재하는 영역이다. 이 MBR의 역할은 이 저장장치에 어떤 파티션이 존재하는지, 어디서부터 어디까지를 차지하는지, 뭐 이런것들을 기록하는 영역인데 다음 그림과함께 자세히 한번 살펴보자.
그림을 매우 못그렸지만, 양해바란다. 글자도 거의 그려버렸다.
앞서 말했듯 MBR은 물리 저장장치의 첫 섹터, 즉 첫 512Byte까지 존재한다.
여기에는 부팅 관련 기능을 하는 어셈블리 코드 즉, 부트코드가 있다. 부트 코드 워치는 0~446 바이트 까지다.
부트 코드 다음에는 파티션 테이블이 존재한다. 파티션테이블은 파티션이 어디서부터 시작하는지 크지는 얼마나되는지 이런 정보들을 담고있다. 이 파티션 테이블은 총 64Byte로 파티션 하나당 16Byte씩 해서 총 네개 파티션을 표현할 수 있다.
마지막으로 시그니쳐가 오는데 이는 마지막 2Byte로 "55 AA" 값을 가진다.
(1) 부트 코드(Boot Code)
부트 코드를 분석하기 앞서 먼저 MBR 영역을 덤프를 떠보자. winhex 나.. 뭐 다른 MBR을 덤프 . 뜰수 있는 도구를 사용할 수도 있겠지만.. 지금 당장 기억이 나지 않으므로 파이썬 코드로 한번 덤프를 떠보겠다.
다만 여기서 주의할점은 만약 물리 저장장치가 여러개 마운트 되어 있다면 사용 중인 물리 드라이브가 몇 번물리 장치인지는 여러분들이 잘 확인해야 한다는 것이다. 그리고 관리자 권한으로 코드를 실행해야된다. 그렇지않으면 Permission Error가 발생할 것이다.
아무튼 위 코드를 실행하면 쉘 경로에 'mbr' 파일이 생성된다. 'HxD' 라는 도구를 사용해서 해당 파일을 열어보겠다. (*HxD를 이용해서도 MBR 영역을 확인할 수 있네요)
mbr 파일에 부트 코드가 저장되어 있는 것을 확인할 수 있다.
위 사진처럼 부트 코드를 디스어셈블 해보았다. 자세히 분석하려니 이 글의 범위를 넘는 것 같아서 다른 글에서 포스팅 해야할것 같다는 생각이 든다.
아무튼 16bit 어셈블리 코드로 작성되어 있고, 이 코드의 기능은 파티션 테이블을 읽어 부팅가능한 파티션의 VBR영역을 메모리의 7c00 주소에 적재하는 것이다.
(2) 파티션 테이블(Partition Table)
파이션 테이블은 파티션에관한 정보를 담고있다. 일단 그림을 한번 그려보았는데 미적 감각이 없어서 뭔가 못생겨보이지만 양해바란다.
여기서 CHS Address 두 개는 현재 거의 쓰이지않는다고 생각하면된다. 우리가 생각해야 할 것은 Boot flag, Partition Type, LBA Address 시작 주소, 파티션 총 섹터 수 이렇게 네 개다. 간단하게 어떤 의미가 있는지 설명하고 넘어가겠다.
(0x00 ~ 0x01, 1 Byte) Boot Flag
Bootable 한지 아닌지를 의미. 0x00 또는 0x80 값을 가지는데 0x00은 비활성 상태, 0x80은 활성 상태를 의미한다. 즉 부팅 가능하다는 얘기다.
위의 MBR 영역에서 파티션 테이블만 따로 잘라와 보았다. 첫 번째 파티션이 부팅가능하기 때문에 0x80 값을 가지는 것을 볼 수 있다.
(0x01 ~ 0x04, 3 Byte) CHS(Cylinder-Header-Sector) Address 시작 주소
(0x05 ~ 0x08, 3 Byte) CHS(Cylinder-Header-Sector) Address 끝 주소
실린더 헤더 섹터를 나타내던 정보. 현재는 쓰이지 않으니 넘어가겠다.
(0x08 ~ 0x0C, 4 Byte) LBA Address 시작 주소
LBA(Logical Block Address) 섹터가 시작하는 위치를 가리킨다. CHS 주소 지정방식에서 용량의 한계를 극복하기 위해 대체된 주소 인덱싱 방법이다.
위의 파티션 테이블의 첫 번째 데이터를 확인해보면 00 08 00 00 인 것을 알 수 있다. 이를 빅 엔디안으로 변환하면 0x800 이 되고, 0x800 은 10진수로 2048이다. 즉 2048번째 섹터를 찾아가면 된다.
만약 섹터가 너무 많아서 찾아가는게 힘들다면, 0x800(섹터순서) * 0x200(섹터크기) = 0x100000 주소를 찾아가면 된다.
(0x0C ~ 0x0F, 4 Byte) 파티션의 총 섹터 수
현재 파티션에 존재하는 총 섹터의 개수를 의미한다. 위의 첫 번째 파티션 테이블에서 확인할 수 있는 값은 00 90 01 00 이고, 이를 빅엔디안으로 변환하면 19,000(16진수)이 된다.
이것으로 현재 파티션의 전체 용량을 계산해 볼 수도있는데 일반적으로 윈도우 운영체제에서 지정하는 섹터의 기본 값은 512 Byte, 16진수로는 0x200 Byte다. 따라서 0x19000 * 0x200 을 계산하면 0x320 0000 값이 나오는데, 약 50MB 정도된다.
두 번째 파티션의 3E 55 FE 18을 빅엔디안으로 변환하면 18FE553E가 되고, 용량을 계산해보면 약 199 GB가 나온다. 여러분이 한번 직접 계산해보길 바란다.
MBR을 사용하면 파티션 하나 당 2TB박에 사용하지 못한다는 말을 들어본 적이 있을 것이다. 그 이유가 바로 이 파티션의 총 섹터 수와 관련이 있는데, 이 섹터 수가 가질 수 있는 최대 값은 4bit 이므로 FF FF FF FF 이다. 해당 값으로 전체 용량을 계산해보면 약 2TB가 나온다.