Creating an OPENSTEP Boot CD

From 흡혈양파의 인터넷工房
Jump to navigation Jump to search
OPENSTEP Boot CD 만들기


m68k 하드웨어에서 OPENSTEP 4.2 는 어떻게 부팅되나요?

NEXTSTEP/OPENSTEP CD 를 sparc 과 m68k 하드웨어 양쪽다 부팅되게는 할 수 없습니다. NEXTSTEP 3.3 은 한장의 installation CD 에 m68k/i386 이, 다른 installation CD 에 sparc/hppa 가 구성되어있습니다. sprac 은 하드웨어가 bootloader 시작점을 CD의 offset 0×00000200 (512) 에서 제공되는걸로 처리합니다. m68k 에서는 CD의 제일 처음의 disklable 에서 시작되고, 이 disklabel 은 CD 의 어딘가 다른곳에 bootloader 가 있다는걸 가리킵니다. m68k 의 dislabel 은 7240 바이트의 크기를 가지며, 크기덕분에 sparc-bootable CD 의 첫번째 512 바이트에는 크기가 맞지 않습니다.


OPENSTEP 4.2 는 한장의 m68k/i386/sparc "User" installation CD 에 모든것이 있습니다.(아마도 hppa 플랫폼지원이 빠진덕분이라 생각됩니다) 이렇게 세개의 플랫폼을 놓고봤을때, NeXT사 는 sparc 하드웨어를 위한 CD 부팅을 선택한것 같습니다. sparc 의 메직넘버인 01 03 01 07 가 CD 의 offset 0×00000200 에서 제공되거든요. CD 에서 부팅할경우 주의할점은 sparc 워크스테이션은 추가적으로 2048 바이트의 섹터를 포함하는 512바이트의 섹터가 제공되는 SCSI CDROM 드라이브가 필요하다는 거에요. 오래된 Plextor, Yamaha, Pioneer 드라이버는 점퍼를 통해서 관련된 섹터크기를 세팅할 수 있습니다. m68k 하드웨어에서 CD 로 부팅을 시도하면 다음과 같은 에러를 볼 수 있습니다:

  Bad version 0x80000000
  Bad cksum
  Bad version 0x0
  Bad cksum
  Bad label


m68k/i386 설치 디스켓과 i386 드라이버 디스켓은 3.5인치 1.44M 형식으로 되어있습니다. 설치디스켓은 m68k 하드웨어의 설치과정의 bootstrap 에서 사용됩니다. 사실 m68k 의 부트로더를 설치디스켓에서 찾을수가 없었는데, 어느날 생각해보니 m68k 하드웨어의 ROM에 boot process 가 있었던게 함정이었고, CD 의 offset 0×00002000 또는 offset 0x00003C00 위치의 disklabel 중 하나를 복사해서 로딩 하도록 동작하고 있었습니다. disklabel 에는 ROM 에 있는 m68k bootloader 가 cd 에 있는 부트과정을 진행하고, m68k 용 "sdmack" 커널을 로딩할 수 있도록 해주는 정보가 있습니다.


i386 하드웨어에서 OPENSTEP 4.2 는 어떻게 부팅되나요?

i386 ROM 은 디스켓의 시작부분부터 512 바이트 까지의 i386 initial "B1" bootloader 를 로딩합니다. 이후 진행은 initial bootloader 로서 표준적인 i386 부트로더로서 디스켓의 offset 0x00008000 위치[1]에 있습니다. 부팅과정은 i386 커널인 "mach_kernel" 를 로드하고, "sarld" 를 로드하며, 사용자에게 드라이버 디스켓을 넣으라는 프롬프트를 표시해주고(CD를 일어들이기위해 IDE 또는 SCSI CD 드라이브를 위한 드라이버를 로딩해야합니다), 드라이버 디스켓을 로딩한후 CD 에서 하드디스크로 파일을 복사하는 과정으로 설치를 진행하게 됩니다.


m68k 부팅을 위한 사용자 OPENSTEP CD 만들기

예전부터 m68k 하드웨어는 CD 의 시작부분에 있는 disklabel 을 참고하도록 되어있으며, CD 의 offset 0x00002000 또는 offset 0x00003C00 위치한 중복된 disklabel 둘 중 하나를 복사만 하면 됩니다. 아래와 같은 방법으로 OPENSTEP 4.2 CD 의 raw ISO 이미지에서 disklabel 을 추출해보겠습니다:

dd bs=1 count=7680 if=OPENSTEP42CD.iso of=OPENSTEP42CD.lbl skip=8192
cd 의 iso image 에서 offset 0x2000 부터의 내용입니다. 위의 내용은 offset 0x2000 부터 0x3dff 까지의 내용을 복사해서 lbl 파일로 만드는 작업으로서 위에 언급된 중복된 disklabel 을 둘 다 하나의 파일로 복사하는 겁니다


추출한 disklabel 을 CD 이미지의 시작위치로 덮어씌우는 방법은 다음과 같습니다:

dd bs=1 count=7680 if=OPENSTEP42CD.lbl of=OPENSTEP42CD.iso
위의 작업은 0x0000 부터 0x1DFF 까지를 추출한 lbl 로 덮어 씌우는 작업으로서 실제로 disklabel 이 있는 offset 0x2000 이전의 영역에 데이터를 씌우게 됩니다.


m68k 에서 부팅이 되게 만들기 위해서는 disklabel 에서 몇개의 바이트를 변경할 필요가 있습니다. disklabel 의 구조는 File:Bootblock.h[2] 에서 찾을 수 있습니다.


첫번째로 변경해야 할것은 disklabel 에 있는 block number 입니다. disklabel 의 원래값이 offset 0x00002000 위치일때, block number 는 4[3] 가 됩니다(하나의 iso 하나의 블록(sector)은 2048 바이트입니다) 새로 세팅되는 disklabel 은 disk(iso파일) 내의 블록번호 0번 에서 시작됩니다.


두번째로 변경할 바이트는 boot block(bootloader) 의 포인터에 대한 내용입니다. disklabel 에는 두개의 포인터가 있습니다. 첫번째 포인터는 hppa bootloader (block 0x10) 을 가리키며, 두번째 포인터는 m68k bootloader (block 0x30) 를 가리킵니다. hppa bootloader 때문에 좀 놀랐는데 hppa 플랫폼은 OPENSTEP 에서 더이상 지원되지 않기 때문이죠. 추가로 주의해야 할 점은 sparc bootloader 는 offset 0x00000200 부터 시작되며 새롭게 덮어씌우는 disklabel 과 위치가 겹쳐진다는 건데, 덕분에 새롭게 만들 CD 이미지에서는 sparc-bootable 이 지원되지 못합니다. 이제부터 m68k boot block 만 가리키는 disklabel 의 boot block 포인터를 변경할겁니다. - 첫째포인터는 0x30, 두번째 포인터는 0xFFFFFFFF 으로 세팅할겁니다.


세번째로 변경할 바이트는 bootloader 에서 기본커널을 로딩하는 작업에 필요합니다. 원래의 disklabel 에는 커널이름이 "mach_kernel" 로 되어있습니다. 비록 CD 에서 "mach_kernel" 이 제공되기는 합니다만 이건 tri-fat 바이너리입니다. m68k 부트로더는 tri-fat 바이너리를 로딩할 수 없으며, 그대신 "sdmach" 라는 이름의 Mach-O 바이너리의 로딩을 필요로 합니다. 비록 수동으로 ROM boot 프롬프트에서 커널의 이름을 별도로 입력한다고 해도, disklabel 은 변경한 "sdmach" 대신 "mach_kernel" 을 기본값으로 사용하게 됩니다.


마지막으로 변경할 바이트는 disklabel 의 체크섬에 관련되어 있습니다. File:NS CKSUM.ZIP 는 작은 프로그램이며 체크섬 계산방법을 알려줍니다. 체크섬에 대한 데이터를 이전의 disklabel 에서 바이트단위로 읽은다음, 16비트 HEX 코드값으로 나오는 결과를 새로운 체크섬 값으로 사용합니다. OPENSTEP 4.2 CD 의 dislabel 값을 갱신하면, checksum 값은 0xCE22 로 계산됩니다.[4]


i386 용 부팅가능한 "USER" OPENSTEP CD 만들기

OPENSTEP 의 i386 부트로더는 설치 디스켓의 boot block 에 위치해 있습니다. 이 부트로더는 CD 의 자료중 /usr/standalone/i386/boot 바이너리 를 복사한것입니다. 추가적으로 첫번째 디스켓의 512 바이트(offset 0x200 까지)의 에는 /usr/standalone/i386/boot1f 바이너리를 복사한것이 들어가 있습니다. m68k 하드웨어와 i386 하드웨어는 CD의 첫번째 블록(offset 0x8000)에 대한 bootstrap 과정이 서로 다르게 되어있습니다[5]. i386 하드웨어는 El-Torito 규격에 의해 CD 의 bootstrapping 을 만들 수 있습니다. El-Torito 규격은 IBM 과 Pheonix 가 만들었죠. El-Torito CD 를 사용하면 BIOS 에서 bootstrap 이미지를 로드하도록 처리할 수 있습니다.. bootstrap 이미지는 "A:" 디스켓 드라이브처럼 취급됩니다.


El-Torito 의 한가지 제약사항은 한개의 이미지만 bootstrap 으로 사용할 수 있다는겁니다. CD 부팅에서 다중 bootstrap 이미지 선택을 지원 하고싶다고 해도, bootstrap 에는 한개의 이미지만 사용할 수 있습니다(CD 에 있는 다른 이미지를 "B:" 드라이브로 매핑할 수 없거든요) 또한 El-Torito 부팅과정에서는 이미지를 "swap" 하는것도 할 수 없는데, 여기서 문제는 OPENSTEP i386 설치과정에서는 설치디스켓을 빼고 드라이버 디스켓을 넣는 과정이 요구된다는거죠.


"mack_kernel" 과 "sarld" 두개만으로도 1.44M 설치디스크에는 어떤 추가 드라이버도 용량상의 문제로 덧붙일 수 없습니다. 그래서 고민해본결과 좋은 방법이 생각났는데 El-Torito의 bootstrap 이미지로 2.88M 디스켓 이미지를 사용하는 방법이죠. 만약 OPENSTEP 설치디스켓과 드라이버 디스켓을 하나의 2.88M 디스켓으로 합칠 수 있다면 이걸 이용해서 CD 로 부팅을 하게할 수 있습니다.


2.88M 디스켓을 생성하는데는 몇가지 방법이 있습니다. 한가지 방법은 2.88M 스카시 디스크 드라이브를 이용하는 방법이며, 적당한 2.88M 디스켓이 초기화되어야 하고 두개의 OPENSTEP 디스켓을 새로운 디스켓으로 넣는 방법입니다. 이 작업은 윈도우머신에서 진행했고, 가상머신에서 실행되는 OPENSTEP 을 이용해서 디스켓 이미지를 셋업하는 방법을 선택해 봤습니다.


일단 2.88M (2,949,120 bytes) 의 파일을 생성합니다. 어떤 유틸리티를 사용해도 같은 사이즈의 파일만 생성할 수 있으면 됩니다. 파일생성시 내용은 상관없는데, 어차피 OPENSTEP 에서 다시 초기화하게 될 것이기 때문입니다. 그리고 2.88M 파일을 VirtualBox 의 가상플로피드라이브로 mount 합니다. 하지만 이렇게 플로피 드라이브를 취급한다고 해도, OPENSTEP i386 플로피 드라이버는 2.88M 디스크를 초기화할 수 없으며 1.44M 까지만 사용하게 됩니다. VirtualBox 는 BIOS 설정화면을 제공하지 않기 때문에 어디서도 "A:" 를 2.88M 드라이브로 변경할 수는 없습니다. Virtual PC 2007 은 BIOS 설정화면을 가지고 있지만, 별다르게 진행된 내용이 보고된건 없는데, Virtual PC 2007 에서는 OPENSTEP 설치과정을 processor exception 때문에 진행할 수 없기 때문입니다.


사실은 2.88M 파일을 Vitual IDE disk 를 이용해서 VirtualBox 에 mount시키면 됩니다. VMware형식의 File:F288.vmdk.zip 파일은 160 cylinders, 2 heads, and 18 sectors/track 의 정보를 가진 File:F288.img.zip 가상디스크에 대한 내용을 선언하고 있으며 선언된 내용대로 사용할 수 있게 해줍니다. IDE 섹터는 512의 길이가 되며 최종적으로 160*2*18*512 = 2.88M 이 됩니다.


일단 OPENSTEP 이 실행되고있는 VirtualBox 에 이 vmdk를 할당하고, 다음의 과정으로 2.88M 디스크를 초기화해보겠습니다:

/usr/etc/disk -i -b -B1 /usr/standalone/i386/boot1f /dev/rhd1a
-i 는 초기화, -b 는 부팅가능 -B[n]은 원하는 boot block에 파일을 넣는걸 나타냅니다. 그리고 제공되는 image를 바로 사용한다면 OPENSTEP 구동시 자동으로 Mount 되어버리기 때문에 mount 상태를 체크한다음 unmount 를 하고 진행해주시기 바랍니다


만들어진 새 디스크를 OPENSTEP 에서 mount 하겠습니다:

mkdir /F288 
mount /dev/hd1a /F288


그리고 설치디스켓과 드라이버 디스켓으로부터 파일을 복사하겠습니다:

cp -r /4.2mach_Install/* /F288
cp -r /4.2mach_Drivers/* /F288


모든 드라이버를 복사할 필요는 없으며 일부는 복사하지 않을겁니다. 대부분의 SCSI 드라이버는 복사하지 않았으며, 설치할때 사용할 IDE/ATAPI CD drive 에 관련된것만 복사했습니다. /F288/private/Drivers/i386/System.config/Instance0.table 파일에서 "Prompt For Driver Disk" 부분을 "No" 라고 편집합니다. 이렇게 하면 El-Torito bootstrap 이미지에 사용할 "F288.img" 이라는 2.88M 파일이 만들어지게 됩니다.[6]


어떻게 해야 OPENSTEP 4.2 CD 와 2.88M bootstrap 이미지를 하나의 El-Torito ISO9660 CD 로 만들 수 있을까요? OPENSTEP 4.2 CD 는 ISO9660 형식이 아닙니다. OPENSTEP 의 CD 는 4.3BSD UFS 변종 형식으로 되어있습니다. ISO9660 형식의 CD 에 상대적 위치로 UFS 파일시스템을 위치시키려면 어떻게 해야 할까요? bootblock.h 파일에는 disklabel 의 바이트 내용중 실제 UFS 파일시스템에 대한 앞부분의 위치정보인 "front porch" 의 명세가 있습니다. "front porch" 에는 housekeeping 정보와 UFS 파일시스템의 앞부분이 포함되어 있습니다. raw UFS filesystem 은 CD 이미지에서 추출할 수 있습니다.

dd bs=2048 if=OPENSTEP42CD.iso of=OPENSTEP42CD.ufs skip=80


"F288.img" 과 "OPENSTEP42CD.ufs" 를 가지고 있다면, CD-record 어플리케이션을 작동시켜서 El-Torito CD 이미지를 생성하도록 합니다. ISO9660 파일시스템에는 하나의 OPENSTEP42CD.ufs 파일만 포함되면 됩니다. 생성된 CD 이미지에서, offset 0x360000 부터 UFS 파일시스템이 시작되는걸 확인할 수 있습니다.[7]


CD 이미지에 block 0 disklabel 을 삽입하는게 필요하지만, 그전에 disklabel 의 몇몇 바이트를 변경해야만 합니다.


처음 변경해야할 바이트는 "front porch"의 사이즈 변경에 필요합니다. UFS 파일시스템이 offset 0x360000 으로 옮겨졌을때, "front porch" 의 값은 0x06C0 (1728 blocks) 가 됩니다[8][9]. 다음으로 변경할 바이트는 disklabel 의 체크섬에 대한 내용입니다. disklabel 을 업데이트할때, 체크섬의 계산값은 0xD492 가 됩니다.[10]


disklabel을 다시한번 CD 이미지의 시작부분에 덮어씌우도록 하겠습니다:

dd bs=1 count=7680 if=OPENSTEP42CD.Block00.ElTorito.lbl of=Disc.iso


m68k 부팅과 i386 부팅용 OPENSTEP CD 생성하기

생각을 좀 더해보면, m68k 와 i386 양쪽에서 부팅가능한 CD 를 만들 수 있습니다. ISO 9660 볼륨의 명세는 offset 0x00008000 (block 16) 부터 시작됩니다. 32KB 는 disk label 과 m68k bootloader 에 사용되기에는 부족합니다. /usr/standalone/boot.cdrom 파일의 크기는 49812 바이트 입니다.


El-Torito CD 이미지를 보면, ISO9660 파일시스템은 2.88M bootstrap 이미지와 함께 OPENSTEP42CD.ufs 파일과 boot.cdrom 이라는 두개의 파일을 포함하고 있습니다. disklabel 의 순서에 대해 몇가지 변경을 해보겠습니다. UFS 파일시스템은 CD 의 offset 0x0036C800 부터 시작되며, "front porch" 의 값은 0x06D9 (1753 blocks) 일겁니다. boot.cdrom 이미지는 CD 의 offset 0x0036C000 부터 시작됩니다. 첫번째 boot 블록의 포인터는 0x06C0, 그리고 두번째 블록의 포인터는 0xFFFFFFFF 의 왼쪽이 됩니다. disklabel 의 새로운 체크섬은 0xDB3B 입니다.


CD 이미지의 시작지점에 있는 dislabel 을 새로 덮어씌워 보겠습니다:

dd bs=1 count=7680 if=OPENSTEP42CD.Block00.ElTorito.m68k.lbl of=Disc.iso


변경된 Disk.iso 파일로, m68k 플랫폼(CD부팅이 가능한 마지막 ROM 을 가지고있다면) 과 i386 플랫폼 양쪽에서 부팅가능한 CD를 만드세요.


기타파일들

File:OPENSTEP42CD.Block00.lbl.zip

File:OPENSTEP42CD.Block00.ElTorito.lbl.zip

File:OPENSTEP42CD.Block00.ElTorito.m68k.lbl.zip


Notes

  1. iso 의 구성정보에서 실제 ISO영역도 0x8000 부터 시작됩니다.[여기페이지] 를 참고해주세요
  2. NetBSD의 파일입니다.
  3. 블록단위 2048 * 4 = 8192 to 2진수변환 result 0x2000 이 됩니다
  4. lbl 파일의 내용을 전부 수정한다음 checksum을 계산한다. checksum 계산 프로그램은 offset 0x22E 이전까지만의 내용을 대상으로 checksum을 계산하도록 되어있기 때문에 별도로 신경쓸 부분은 없다
  5. mkisofs 로 iso 파일을 만들게 되면 0x8000 에 01 43 44 30 30 31 같은 값으로 iso 파일이 시작됩니다. 물론 원본 OPENSTEP 4.2 CD 는 이런값으로 시작되지 않습니다.
  6. 저는 SCSI driver 를 모두 제거하고 beta driver 1 번에 있는 EIDE 파일을 새로 넣었습니다.
  7. linux 에서 Temp 디렉토리에 floppy image 와 ufs image 를 넣고 Temp 디렉토리의 바로 아래에서 mkisofs -b F288_onioncustom.img -V OPENSTEP_4.2J -hide F288_onioncustom.img -R -J -o result.iso Temp 이런 방법으로 iso 를 만들었습니다. 제 경우는 0x2e0800 에서 ufs가 시작됩니다
  8. "front porch"는 결국 UFS 파일시스템의 시작주소를 의미합니다
  9. 저는 0x2e0800 을 10진수로 바꿔서 block size 인 2048 로 나눈다음 다시 16진수로 변환하면 0x05C1 이라는 값이 됩니다. lbl 파일에서 0x0070 의 주소값을 계산된 값으로 바꿔주면 됩니다
  10. 제 경우는 변경한 lbl 파일의 체크섬이 ABE9 이라는 값으로 나왔습니다. 0x22e 주소에 ABE9 를 넣었습니다