반응형

A20 게이트PC의 역사와 관계가 있다 해도 과언이 아닙니다.

 

A20은 주소 라인의 번호를 의미하며 시스템 포트와 BIOS 서비스를 이용하여 A20게이트를 활성화합니다.

 


 

→ A20 게이트의 의미와 용도

 

초창기 XT PC주소를 최대 1MB 주소까지 접근할 수 있었지만 리얼 모드에서 세그먼트와 오프셋으로 접근할 수 있는 최대 주소는 0xFFFF:0xFFFF로 1MB가 넘는 0x10FFEF까지 접근할 수 있습니다.

 

하드웨어의 한계로 1MB가 넘는 주소로 접근하면, 하위 주소만 남아 실제로는 0xFFEF로 인식되었습니다.

 

XT PC가 주로 사용되던 시절에는 이러한 주소의 한계를 이용하여 프로그램이 문제없이 동작했지만 이후 16MB 주소까지 접근할 수 있는 AT PC가 탄생하면서 기존의 XT PC용 프로그램을 실행하는데 문제가 생겼습니다.

 

그 이유는 기존의 XT PC 프로그램 중에서 XT PC의 특수한 주소 계산법(1MB 이상의 주소를 1MB이하의 주소에 매핑)을 이용하는 프로그램들이었습니다.

 

그렇기에 이러한 호환성의 문제를 해결하기 위해 도입된 것이 A20 게이트 입니다.

 

A20 게이트에서 A20의 의미는 주소의 20번째 비트를 뜻하며, 주소 20번째 비트를 활성화하거나 비활성화하여 XT PC의 주소 계산 방식과 호환성을 유지시키는데, A20 게이트가 비활성화되면 주소 라인의 20번째(1M의 위치)가 항상 0으로 고정되므로 선형 주소가 0x10FFEF가 되더라도 0xFFEF로 처리할 수 있습니다.

 

AT PC는 부팅 과정을 완료하고 나서 A20 게이트를 무조건 0으로 설정하여 XT PC와 호환성을 유지했으며, A20 게이트를 활성화했을 때만 20번째 주소 비트가 정상적으로 동작하게 했습니다.

 

이것 때문에 이전에 있었던 문제를 일으킨 것입니다.

 

아래는 A20 게이트의 비활성화에 따른 선형 주소의 변화를 나타낸 것입니다.

 

A20 게이트 비활성화에 따른 선형 주소의 변화( https://kkamagui.tistory.com/m/619?category=19076 )

 

A20 게이트가 비활성화된 상태에서는 주소 라인의 20번째 bit가 항상 0으로 설정되므로 홀수 MB에는 접근할 수 없습니다.

 

최초 부팅된 이후의 상태는 A20 게이트가 비활성화된 상태이므로 1MB ~ 4MB까지의 주소를 초기화하면 홀수 MB 영역을 제외한 0 ~ 1MB와 2MB ~ 3MB 영역을 초기화하게 되지만, 0 ~ 1MB 영역은 BIOS와 보호 모드 커널 영역이 사용 중이므로 현재 커널이 수행 중인 부분이 초기화하게 되어 문제가 생깁니다.

 

하지만 간혹 최신 BIOS 중에서 A20 게이트를 사용하지 않거나 기본 값으로 1로 설정하기 때문에 문제없이 실행되는 경우도 있습니다.

 

아래는 A20 게이트 비활성화에 따른 접근 가능한 메모리 공간의 변화를 나타낸 것입니다.

 

A20 게이트 비활성화에 따른 선형 주소의 변화( https://kkamagui.tistory.com/m/619?category=19076 )

 

참고 : https://kkamagui.tistory.com/m/619?category=19076

 


 

→ A20 게이트 활성화 방법

 

A20 게이트를 활성화하는 방법은 크게 세 가지가 있습니다.

 

● 키보드 컨트롤러(Keyboard Controller)로 활성화하는 방법

시스템 컨트롤 포트(System Control Port)로 활성화하는 방법

BIOS 서비스로 활성화하는 방법

 

▶ 키보드 컨트롤러(Keyboard Controller)로 활성화하는 방법

AT PC의 초창기 시절부터 사용되던 방법입니다.

AT PC의 키보드 컨트롤러에 A20 게이트를 연결하여 키보드 컨트롤러를 통해 제어합니다.

키보드 컨트롤러를 통하는 방법은 속도가 느리고 코드가 복잡하지만, PS/2 방식의 키보드/마우스를 지원하는 PC라면 어디서나 가용 가능합니다.

 

시스템 컨트롤 포트(System Control Port)로 활성화하는 방법

키보드 컨트롤러의 대안입니다.

시스템 제어에 관련된 I/O 포트를 통해 A20 게이트를 활성화합니다.

시스템 포트를 통한 방법이 키보드 컨트롤러를 통하는 방법보다 빠르고 코드가 간략합니다.

 

▶ BIOS 서비스로 활성화하는 방법

486 프로세서를 지원하는 BIOS에서 처음 도입되었습니다.

BIOS 서비스 중 시스템에 관련된 서비스를 통해 A20 게이트를 활성화합니다.

PC의 전반적인 정보를 관리하는 BIOS의 서비스를 사용하므로 세 가지 방법 중 가장 확실한 방법입니다.

 

PC에 있는 프로세서의 코어 수가 2개 이상(듀얼 코어)이거나 64bit를 지원하는 프로세서라면 위의 세 가지 방법 중 최소 두 가지는 지원할 것입니다.

 

시스템 컨트롤 포트BIOS 서비스를 사용하여 A20 게이트를 활성화하고, 추후에 키보드 컨트롤러를 제어하는 방법을 알아봅니다.

 


 

-> 시스템 컨트롤 포트로 A20 게이트 활성화 하는 방법

 

시스템 컨트롤 포트I/O 포트 주소의 0x92에 위치하며, A20 게이트부터 하드 디스크 LED에 이르기까지 여러 가지 시스템 옵션을 담당합니다.

 

 

참고)

주변 장치에 I/O을 수행하는 방식은 크게 메모리 맵 I/O 방식포트 맵 I/O 방식으로 나뉩니다.

 

메모리 맵 I/O 방식물리 메모리 주소를 I/O 용도로 할당하는 방식으로, I/O 관련 명령어가 별도로 필요하지 않고, 메모리 접근 명령어(mov)로 I/O를 수행할 수 있는 것이 특징입니다.

 

메모리 주소를 I/O로 사용하므로 메모리에 접근하는 시점에 즉시 물리 메모리에 접근하여 작업을 수행해야 정상적으로 동작하기 때문에 만약 프로세서의 캐시가 활성화 되어 있으면 캐시 정책에 따라 물리 메모리에 접근하는 시점에 차이가 있으므로 해당 메모리 주소는 캐시를 사용하지 않게 설정해야 합니다.

 

 

포트 맵 I/O 방식메모리 주소와 별개로 I/O 전용 주소를 할당하는 방식으로, 해당 포트 주소에 접근하려면 특수한 명령어(in/out)가 필요합니다.

포트 맵 I/O 방식은 포트 주소를 별도로 할당하므로 메모리 주소를 효율적으로 사용할 수 있는 것이 특징입니다.

 

x86 계열의 프로세서는 위의 두 방식 모두 사용합니다.

 

 

아래는 시스템 컨트롤 포트의 각 비트와 그 의미를 정리한 것입니다.

 

시스템 컨트롤 포트의 각 비트와 의미

 

A20 게이트를 활성화하기 위해서는 시스템 컨트롤 포트의 비트 1만 1로 설정하면 됩니다.

 

시스템 컨트롤 포트I/O 포트에 있으므로 이에 접근하려면 별도의 명령어를 사용해야 하는데, x86 프로세서는 I/O 포트에 접근하는 in과 out 명령어를 제공하므로 아래와 같이 in / out 명령어로 시스템 컨트롤 포트에 접근하여 A20 게이트를 활성화하는 코드를 작성합니다.

 

시스템 컨트롤 포트를 통해 A20 게이트를 활성화하는 코드

 


 

-> BIOS 서비스로 A20 게이트 활성화 하는 방법

 

BIOS 서비스A20 게이트를 활성화하는 방법시스템 컨트롤 포트를 사용하는 것보다 훨씬 간단한데, A20 게이트 관련 설정 값을 AX 레지스터에 넣고 나서 A20 게이트를 활성화하는 BIOS의 시스템 서비스(인터럽트 벡터 0x15)를 호출하면 됩니다.

 

BIOS 서비스 중 A20 게이트 관련 기능은 BIOS의 시스템 서비스에 포함되어 있으며, 시스템 서비스는 인터럽트 벡터 테이블의 0x15에 있습니다.

 

BIOS의 시스템 서비스(0x15) 중 A20 게이트 관련 기능 목록

 

아래는 BIOS 서비스를 호출하여 A20 게이트를 활성화하는 코드입니다.

 

BIOS 서비스를 통해 A20 게이트를 활성화하는 코드

 


 

→ A20 게이트 적용과 메모리 크기 검사

 

바로 위의 A20 게이트를 활성화하는 코드를 FS64 OS에 적용해보고 메모리 부족으로 발생할 수 있는 문제를 피하기 위해 PC에 설치된 메인 메모리가 최소 크기를 만족하는지 검사하는 기능을 추가합니다.

 


 

→ A20 게이트 활성화 코드 적용

 

시스템 컨트롤 포트를 사용하는 방법BIOS 서비스를 사용하는 방법 이 두 가지 방법 중에 한 가지만 사용해도 A20 게이트를 활성화할 수 있지만, BIOS마다 구현의 차이가 있을 수 있기에 두 가지 모두 사용합니다.

 

먼저, 가장 믿을만한 BIOS 서비스를 실행하고, BIOS 서비스가 실패할 경우 시스템 컨트롤 포트를 사용하는 순서로 합니다.

 

BIOS 서비스를 사용하려면 리얼 모드여야 하므로 A20 게이트 활성화 코드는 부트 로더 또는 보호 모드 커널 엔트리 포인트에 추가해야 합니다.

 

의미상 보호 모드 커널과 관계가 있으므로 보호 모드 엔트리에 추가합니다.

 

아래는 수정된 보호 모드 엔트리 포인트 파일(01.Kernel32/Source/EntryPoint.s)의 일부입니다.

 

세그먼트 레지스터의 초기화 이후 BIOS 서비스를 실행하여 A20 게이트를 활성화하고, 실패할 경우 시스템 컨트롤 포트를 통해 다시 시도합니다.

 

A20 게이트 활성화 코드가 적용된 보호 모드 엔트리 포인트 소스 파일(01.Kernel32/Source/EntryPoint.s)

 

완성된 FS64 OS 이미지를 플로피 디스크로 옮긴 뒤 실제 PC로 부팅하면 QEMU에서와 같은 화면이 뜰 것입니다.

 

이제 1MB 이상의 메모리에 완벽하게 접근할 수 있게 되어 4GB 메모리를 사용할 수 있습니다.

 

앞으로 이 공간을 여러 구역으로 나누어 멀티태스킹, 파일 시스템, 동적 메모리 관리, 애플리케이션 메모리 등의 용도로 사용할 것이지만, 그전에 사용 가능한 메모리의 크기를 검사해야 합니다.

 

보호 모드 커널에서는 최대 4GB 메모리까지 밖에 접근할 수 없으므로 4GB 이상의 메모리가 설치된 경우 이를 정확하게 판단하려면 IA-32e 모드 커널에서 검사해야 하기 때문에 메모리의 전체 크기를 계산하는 코드는 IA-32e 모드 커널에서 검사해야 합니다.

 

아직은 FS64 OS 실행에 필요한 메모리가 충분한지 정도만 검사합니다.

 


 

→ 메모리 크기 검사 기능 추가

 

메모리에 특정 값을 쓰고 다시 읽어서 같은 값이 나오는지 확인하는 것사용 가능한 메모리를 검사하는 가장 확실한 방법입니다.

 

만일 해당 주소가 진짜 물리 메모리라면 쓴 값이 그대로 읽히지만, 해당 주소가 진짜 물리 메모리가 아니라면 쓴 값은 저장되지 않기 때문에 임의의 값이 읽히게 됩니다.

 

물론 메모리의 크기를 BIOS 데이터 영역에서 읽어올 수 있지만, BIOS마다 구현에 차이가 있을 수 있으므로 직접 검사하여 측정합니다.

 

검사하는 방법은 1MB 단위로 주소를 증가시키면서 각 MB의 첫 번째 4byte에 0x12345678를 쓰고 읽어 보는 것으로 합니다.

 

전체 영역을 byte 단위로 검사할 수 있지만, PC에 설치된 메모리의 크기가 GB라면 꽤 많은 시간이 걸리고, 사용하는 PC의 메모리 크기가 MB 또는 GB 단위로 증가함을 고려할 때 MB 단위로 첫 번째 4byte를 검사하는 것으로 충분합니다.

 

 

이제 최소 메모리 용량을 검사하는 함수를 커널 엔트리 포인트에 추가합니다.

 

지금부터는 함수를 추가할 때마다 성공/실패를 출력하는 부분도 같이 추가하기에 화면에 출력하는 메시지 형식도 정리합니다.

 

IA-32 모드의 커널이 위치할 공간을 0으로 초기화하는 함수 전에 미리 메모리의 크기가 64MB 이상인지 검사하여, 그 이하면 에러 메시지를 출력하고 정지하게 하고, kInitializeKernel64Area() 함수 역시 메모리 크기를 검사하는 함수와 마찬가지로 초기화한 값을 검증하고 나서 성공/실패를 반환하게 수정합니다.

 

아래는 최종적으로 변경 사항이 적용된 C 커널 엔트리 포인트 파일(01.Kernel32/Source/Main.c)입니다.

 

최종 C 커널 엔트리 포인트 소스 파일(01.Kernel32/Source/Main.c) 1

 

최종 C 커널 엔트리 포인트 소스 파일(01.Kernel32/Source/Main.c) 2

 

최종 C 커널 엔트리 포인트 소스 파일(01.Kernel32/Source/Main.c) 3

 


 

→ 빌드와 실행

 

지금까지의 변경사항을 모두 적용한 뒤 실행하면 아래와 같이 메모리 크기 검사와 IA-32e 모드 커널 영역 초기화 작업을 정상적으로 통과했다는 메시지가 표시됩니다.

 

메모리가 64MB 이상인 경우

 

정확한 테스트를 위해서 QEMU의 메모리 크기를 최소 크기인 64MB 미만으로 설정하여 메모리 검사가 정상적으로 수행되는지 확인합니다.

 

'-m' 옵션을 32로 수정하여 32MB로 수정합니다.

 

참고)

-m 32 : 가상 머신의 메모리를 32MB로 설정

 

QEMU의 메모리 크기를 32MB로 수정하는 예

 

메모리가 64MB 이하인 경우

 


 

이렇게 1MB 이상의 메모리에 접근하는 데 필요한 작업에 대해서 모두 알아보았고, FS64 OS를 실행하기 위한 최소한의 메모리를 가졌는지 검사하고, IA-32e 모드 커널이 위치할 공간을 0으로 초기화함으로써 64bit로 전환하기 위한 기반을 닦았습니다.

 

반응형

+ Recent posts