[App 개발] OS X 를 지원하지 않는 기종을 위한 커널 해킹 (7)
본문
이 문제를 해결하는 한 가지 방법은 플랫폼 엑스퍼트의 서브클래스를 만들어서 processTopLevel 을 상속한 다음 다른 드라이버를 생성하게끔 하는 것입니다. 하지만 이 방법에는 문제가 있었습니다. 먼저 dtNVRAM 멤버 변수가 private 로 선언되어 있다는 점이었습니다. dtNVRAM 변수는 다른 IODTPlatformExpert 멤버들이 참조하고 있었으므로 이 변수에 그냥 NULL 로 방치해 둘 수 없었습니다. 따라서 IODTNVRAM 의 서브클래스를 만든 다음 이것을 dtNVRAM 변수에 저장해야 했습니다.
IODTPlatformExpert.h 헤더를 변경하여 dtNVRAM 을 private 에서 protected 로 만들 수도 (아니면 제 서브클래스를 friend 로 만들 수도) 있었습니다. 하지만 서브클래스를 만드는 데에는 근본적인 문제들이 있었습니다. IODTNVRAM 은 Mac OS X 버젼별로 변경되어 왔으며, 원래 헤더에 어떠한 예약된 자리도 없이 계속 멤버 변수들과 가상 함수들이 추가되어 왔습니다. 따라서 모든 Mac OS X 버젼에 대응하는 IODTNVRAM 서브클래스를 작성할 수 없었고, 다른 대안이 없지 않는 한 버젼별로 따로따로 드라이버를 작성하는 것을 저는 선호하지 않았습니다.
IODTNVRAM 서브클래스를 만드는 대신, dtNVRAM 멤버 변수를 참조하는 IODTPlatformExpert 클래스의 모든 멤버들을 오버라이드 할 수도 있었습니다. 하지만 dtNVRAM 을 사용하는 IODTPlatformExpert 메쏘드 중 몇 가지는 virtual 로 선언되어 있지 않았습니다. public/protected/private 문제와 달리, 이것은 헤더를 변경하는 것만으로 해결되지 않았습니다. 메쏘드가 vtable 에 없다면 IODTPlatformExpert 의 서브클래스에서 오버라이드할 방법이 없었습니다.
여기서 완전히 막혀버렸습니다. 이 부분은 드라이버의 기본 방식을 따르고 있지 않았기 때문에 제가 원하는 기능을 넣을 수 있는 자리를 찾을 수가 없었습니다.
하지만 저는 하드웨어 버퍼를 읽고 쓰는 완전한 권한을 가지고 있었습니다. 이 부분은 제가 만들었던 PatchedAppleNVRAM 이 역할을 수행하고 있었습니다. 따라서 구 기종에서 신 기종 NVRAM 을 흉내내도록 PatchedAppleNVRAM 을 작성하는 방법을 생각해 냈습니다. 일반적으로 PatchedAppleNVRAM 은 실제 NVRAM 구조를 이해할 필요가 없고, 단순히 IODTNVRAM 에서 마련된 버퍼를 읽고 쓰는 역할일 뿐입니다. 하지만 필요하면 PatchedAppleNVRAM 에서 NVRAM 구조를 이해하여 구 기종과 신 기종간의 NVRAM 구조를 실시간으로 변경하도록 만들 수 있었습니다. 근본적으로 이 작업은 하드웨어로부터 구 기종의 데이터를 읽어서 버퍼에 신 기종의 구조로 변경하여 저장하고, 반대로 신 기종 구조로 씌어진 버퍼를 읽어서 구 기종 구조로 변경하여 하드웨어에 저장하는 일이었습니다. 이렇게 하면 IODTNVRAM 은 신 기종으로 인식하지만, 실제로 하드웨어에는 구 기종의 데이터 구조로 저장됩니다.
문제가 간단하다는 것만 제외하면 PatchedAppleNVRAM 을 가로채는 것은 좋은 일이 아닙니다. 논리적으로 따지면 IODTNVRAM 이나 IODTPlatformExpert 를 가로채야먄 하지요. 하지만 PatchedAppleNVRAM 이 시스템 기본 방식을 잘 따르고 있기 때문에 이것을 가로채는 것이 더 실용적이었습니다.
하지만 한 가지 문제가 남아있었습니다. 모든 미 지원 기종이 PatchedAppleNVRAM 을 사용하고 있는 것은 아니라는 점을 잊고 있었습니다. PMU 방식 기종들은 NVRAM 을 읽고쓰기 위하여 ApplePMUNVRAMController 를 사용하고 있었습니다. 따라서 이 기종들에게는 PatchedAppleNVRAM 이 도움이 되지 않았습니다. 이 부분이 논리적인 면에서 제가 잘못된 부분을 가로채고 있다는 뜻이었습니다. 만약 IODTNVRAM 이나 IODTPlatformExpert 를 가로챘더라면 PMU 기종에서도 동시에 문제가 해결되었을 테지요.
따라서 PatchedAppleNVRAM 으로 대체했던 것처럼 ApplePMUNVRAMController 를 제 드라이버로 바꿔 주어야 했습니다. 코드 작성은 어렵지 않았습니다만, 시스템이 제 드라이버를 사용하도록 하는 것이 약간 까다로웠습니다. 왜냐하면 이 경우에도 기본 방식을 잘 따르고 있지 않았기 때문이었습니다. PMU NVRAM 드라이버도 기본 연결 과정을 이용하지 않고 IODTNVRAM 드라이버 경우처럼 인스턴스를 생성하는 객체 (여기서는 ApplePMU) 와 단단히 연결되어 있었습니다. 앞에서 말씀드린 것처럼 저는 ApplePMU 드라이버의 최신 버젼 소스코드가 없었습니다. 하지만 옛날 버젼에서는 NVRAM 컨트롤러를 다음 방식으로 생성하고 있었습니다.
bool ApplePMU::allocateInterfaces()
{
…
// gets the provider (which property we should look at):
IOService *myProvider = getProvider();
// Do not create the OpenPMUNVRAMController if the
// no-nvram property is set.
if (!myProvider->getProperty("no-nvram")) {
ourNVRAMinterface = new ApplePMUNVRAMController;
if (ourNVRAMinterface != NULL) {
if (ourNVRAMinterface->init(0,this) &&
ourNVRAMinterface->attach(this) &&
ourNVRAMinterface->start(this)) {
…
Listing 15. Another example of how not to instantiate a driver
ApplePMU 클래스는 연결 과정에서 사용되는 nub 으로 생성되지 않고 직접 생성되고 있었으므로, ApplePMU 클래스와 ApplePMUNVRAMController 는 단단히 연결되어 있었습니다.
몇몇 기종에 대하여 저는 ApplePMU 대신 OpenPMU 로 대체해 주었으므로, 이런 경우 문제는 쉽게 해결될 수 있었습니다. 하지만, ApplePMU 는 더 이상 오픈 소스가 아니었고, 제가 무엇인가 빠뜨린 것도 있을 수 있었으므로, ApplePMU 가 정상 작동되는 컴퓨터에서도 OpenPMU 로 대체하고 싶지는 않았습니다.
다행히도 ApplePMU 와 ApplePMUNVRAMController 의 경우는 간단하게 분리할 수 있었습니다. 인스턴스가 ourNVRAMInterface 가 사용되는 경우는 드라이버를 삭제하려는 경우 뿐입니다. ApplePMU 다른 곳에서는 사용되고 있지 않았으므로 ourNVRAMInterface 를 NULL 로 놓아둘 수 있었습니다. 게다가 ApplePMU 클래스는 제공자의 "no-nvram" 프로퍼티를 확인하고 있었습니다. 따라서 제공자가 나타나서 no-nvram 프로퍼티를 설정하는지를 기다리도록 클래스를 작성하였습니다. 그렇다면 ApplePMU 는 ApplePMUNVRAMController 의 인스턴스를 생성하지 않고, 다른 드라이버를 생성하여 붙여줄 것입니다. 이 경우 기본 방식의 일부라도 지켜지고 있었기 때문에 큰 어려움 없이 가로채기를 할 수 있었습니다.
- 결론
Mac OS X 를 미 지원 기종에서 동작하게 하는 작업은 해당 하드웨어에 필요한 장치 드라이버를 제공하는 작업이었습니다. 그리고 애플이 제공하는 커널 및 커널 익스텐션을 수정해 주어야 하는 문제도 다소 있었습니다. 이 작업에 동원된 기술들은 Mac OS X 의 드라이버 모델의 유연성과 정교함 및 가능한 한 기본 방식을 준수한 지혜를 나타내고 있었습니다.
최신글이 없습니다.
최신글이 없습니다.
댓글목록 1
hongjuny님의 댓글
인텔 맥으로 넘어오면서 이제 더 이상 G3 이하 구 기종에 대한 서포트라는 과제는 관심에서 멀어져 가고 있습니다만, XPostFacto 를 설계한 Ryan Rempel 의 문서는 Mac OS X 커널의 구성 및 커널 익스텐션 제작에 관심이 있으신 분들에게 많은 도움이 될 것이라 생각합니다.