ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BOCHS
    프로젝트/운영체제 만들기 2023. 6. 24. 22:27

    글의 참고

    - https://bochs.sourceforge.io/doc/docbook/user/bochsrc.html#BOCHSOPT-FLOPPYAB


    글의 전제

    - 밑줄로 작성된 글은 강조 표시를 의미한다.

    - 그림 출처는 항시 그림 아래에 표시했다.


    글의 내용

    - 설치

    : 리눅스 배포판에서는 기본적으로 아래의 명령어로 설치가 가능하다.

    " sudo apt-get install bochs
    " sudo apt-get install bochs-x

    : 그러나 이건 훼이크다. 나는 위에 처럼 설치하는 걸 추천하지 않는다. BOCHS는 `GDB`와 BOSCH가 자체적으로 제공하는 `인터널 디버깅` 기능 중에서 하나만 선택해야 한다. 기본적으로 `인터널 디버깅`이 선택이 되는데, GDB로 설치해도 상관은 없다. 나는 GDB를 설치해보려고 한다. 일단 소스를 받아야 한다. 여기에 들어가서 아래 보면, 최선 버전을 설치한다.  

     

    : 근데, 문제가 있다. BOCHS에서 `GDTSTUB`를 지원해서 설치하려 했는데 SMP를 사용하면 GDB를 사용할 수 없다고 한다. 즉, GDB는 싱글 프로세서만 디버깅할 수 있다고 한다. 

    make[1]: Entering directory '/home/yohda/workspace/SW/bare-metal/yohdaOS/bochs-2.7/iodev'
    g++ -c  -I.. -I./.. -I../instrument/stubs -I./../instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -pthread   -I/usr/include/SDL2 -D_REENTRANT  devices.cc -o devices.o
    In file included from iodev.h:28:0,
                     from devices.cc:26:
    ../bochs.h:278:2: error: #error GDB stub was written for single processor support. If multiprocessor support is added, then we can remove this check.
     #error GDB stub was written for single processor support.  If multiprocessor support is added, then we can remove this check.
      ^~~~~
    Makefile:114: recipe for target 'devices.o' failed
    make[1]: *** [devices.o] Error 1
    make[1]: Leaving directory '/home/yohda/workspace/SW/bare-metal/yohdaOS/bochs-2.7/iodev'
    Makefile:297: recipe for target 'iodev/libiodev.a' failed
    make: *** [iodev/libiodev.a] Error 2

    : 결국 BOCHS에서는 SMP를 포기해야 할 듯 하다. 어차피 컴파일 시간도 GCC 에 비하면 얼마 안되서 싱글 코어가 끝나면, 다시 컴파일을 해야 겠다. 일단 GDB를 지원하는 방식으로 컴파일을 해야 겠다.

     

    : GDB로 설정해서 설치했지만, 정상적으로 동작을 하지가 않는다. GDB가 연결까지는 되는데, 곧 바로 `SIGTRAP`을 받고 뻗어버린다. 결국, `인터널 디버깅`으로 돌아왔다. 이 번에 OSDEV 에서 그 좋다는 BOCHS의 디버깅을 한 번 익혀봐야 겠다.

     

    - 기본 설정

    : BOCHS를 구동하기 위한 최소 설정이 필요하다. 아래와 같다.

    1" BOCHS 실행 파일이 있어야 한다.
    2" ROM BIOS 이미지가 필요하다. BOCHS에서 제공하는 `BIOS-bochs-latest`를 이용하자.
    3" ROM VGA BIOS 이미지가 필요하다. `VGABIOS-lgpl-latest` 혹은 `VGABIOS-elpin-2.40`을 이용하자.
    4" 최소 한 개의 부팅 이미지가 필요하다. 

     

     

    - 실행

    : 우분투를 기준으로 설명한다. `apt`를 통해 BOCHS를 설치하면 `/usr/bin` 에 설치가 되서 전역적으로 사용이 가능하다. 커널을 실행할 폴더를 들어가서  `bochs`를 입력한다. 그렇면 BOCHS는 바로 시작이 되지는 않는다. 명령창에 `c`를 입력하면 그제서야 실행이 된다. 참고로, `c`는 `continue`의 약자다. 명령창에 `help` 쳐서 사용 가능한 명령어들을 확인 가능하다.

     

     

    - 설정 파일

    : 박스를 구동하면 bochsrc 설정 파일은 아래와 같이 탐색이 된다.

    1" .bochsrc in the current directory
    2" bochsrc in the current directory
    3" bochsrc.txt in the current directory
    4" (win32 only) bochsrc.bxrc in the current directory
    5" (Unix only) .bochsrc in the user's home directory
    6" (Unix only) bochsrc in the /etc directory

     

    : memory

    " 구동할 프로그램에 할당할 RAM을 지정한다. 그런데 복잡하게 2가지 속성이 존재한다. `guest`에는 구동할 프로그램의 

    memory: guest=512, host=256

     

    : megs

    " 위의 `memory` 옵션에서 호스트와 게스트의 RAM 사이즈가 동일할 때, 사용하는 속성이다. 아래처럼 `32` 혹은 `128` 을 지정하면 호스트, 게스트 모두 32MB , 128MB를 사용하게 된다.

    megs: 32
    megs: 128

     

    : romimage

    " ROM BIOS 이미지의 경로를 지정한다. ROM BIOS는 PC가 부트업시에 무엇을 해야 할지를 컨트롤한다. 기본 ROM BIOS는 일반적으로 0xFFFE0000에 로드된다. 그리고 정확하게 128K를 차지한다. BOCHS의 레거시 BIOS는 0xFFFF0000에 로드된고, 사이즈는 정확히 64KB다. $BXSHARE 환경 변수를 이용해서 ROM BIOS의 이미지 위치를 설정할 수 있다. 외부에서 제공되는 BIOS를 사용해도 되지만, BOCHS는 대게 내부에서 제공하는 이미지를 사용할 것을 추천한다. 외부 BIOS를 사용할 경우, 최대 512B를 지원한다. 예시는 아래와 같다.

    romimage: file=bios/BIOS-bochs-latest, options=fastboot
    romimage: file=$BXSHARE/BIOS-bochs-legacy
    romimage: file=mybios.bin, address=0xfff80000

     

     

    " QEMU와 달리 BIOS 이미지를 직접 구동시킨다. BOCHS 측에서는 자기내가 배포하는 BIOS 이미지를 사용할 것을 권한다. 이건 다른말로, 실제 다른 제조사의 BIOS 이미지를 직접 사용해도 된다는 말도 된다.

    romimage: file=bios/BIOS-bochs-latest, options=fastboot
    romimage: file=$BXSHARE/BIOS-bochs-legacy
    romimage: file=mybios.bin, address=0xfff80000

     

    " 우분투에서 BOCHS를 `apt`로 설치할 경우, 기본적으로 `/usr/share/bochs`에 ROM BIOS 이미지들이 설치가 된다.

    /usr/share/bochs$ ll
    total 340
    drwxr-xr-x 3 root root 4096 Mar 20 13:38 ./
    drwxr-xr-x 319 root root 12288 Jun 22 13:09 ../
    -rw-r--r-- 1 root root 131072 Apr 3 2018 BIOS-bochs-latest
    -rw-r--r-- 1 root root 65536 Apr 3 2018 BIOS-bochs-legacy
    -rw-r--r-- 1 root root 131072 Apr 3 2018 BIOS-qemu-latest
    drwxr-xr-x 2 root root 4096 Mar 20 13:38 keymaps/
    lrwxrwxrwx 1 root root 22 Apr 3 2018 VGABIOS-lgpl-latest -> ../vgabios/vgabios.bin

     

     

     

    : vgaromimage

    " ROM BIOS 이미지와 마찬 가지다. BOCHS에게 VGA ROM BIOS가 로드될 위치를 알려준다. ROM VGA BIOS 이미지 또한 BOCHS 에서 제공하는 이미지 사용할 것을 권고한다. 예시는 아래와 같다.

    vgaromimage: file=bios/VGABIOS-elpin-2.40
    vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
    vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus

     

    : ata0, ata1, ata2, ata3

    " ATA 채널을 최대 4개까지 설정이 가능하다. 각 채널은 2개의 I/O 베이스 어드레스와 하나의 IRQ 라인은 반드시 지정해야 한다. ata0 / ata1은 기본적으로 활성화 상태다. 

    ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
    ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
    ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
    ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9

    " BOCHS는 QEMU 보다 어렵다는 말이 많은데, 확실히 그 의미를 알 것 같다. 위의 I/O 주소를 막 지정할 수 없다. 저 주소들은 ATA 스펙에 명시되어 있는 부분이다. 이 글을 참고하자. 

     

     

    : ata0-master, ata0-slave, ata1-*, ata2-*, ata3-*

    " ATA 디스크 드라이브를 디테일하게 설정할 수 있다. type에는 BOCHS 2.0 이상부터는 `disk`, `cdrom`만 지원한다. path는 이미지 파일의 경로를 지정한다. cylinders, heads, spt는 `CHS` 주소 지정 방식을 의미한다. `spt`는 `sectors per track`의 약자다. 여기서 앞에 세 개의 속성을 지정한다고 해서 CHS 주소 지정 방식을 사용한다는 의미는 아니다. 뒤에 `translation` 속성에 따라 달라진다.

    ata0-master: type=disk, path=10M.img, mode=flat, cylinders=306, heads=4, spt=17, translation=none
    ata1-master: type=disk, path=2GB.cow, mode=vmware3, cylinders=5242, heads=16, spt=50, translation=echs
    ata1-slave:  type=disk, path=3GB.img, mode=sparse, cylinders=6541, heads=16, spt=63, translation=auto
    ata2-master: type=disk, path=7GB.img, mode=undoable, cylinders=14563, heads=16, spt=63, translation=lba
    ata2-slave:  type=cdrom, path=iso.sample, status=inserted
    
    ; example
    mode=flat, biosdetect=auto, translation=auto, model="Generic 1234"

     

    : floppya/floppyb

    2.88M 3.5" media:
      floppya: 2_88=a:, status=inserted
    1.44M 3.5" media (write protected):
      floppya: 1_44=floppya.img, status=inserted, write_protected=1
    1.2M  5.25" media:
      floppyb: 1_2=/dev/fd0, status=inserted
    720K  3.5" media:
      floppya: 720k=/usr/local/bochs/images/win95.img, status=inserted
    auto-detect floppy media type:
      floppya: image=floppy.img, status=inserted
    use directory as VFAT media:
      floppya: 1_44=vvfat:path, status=inserted
    1.44M 3.5" floppy drive, no media:
      floppya: type=1_44

     

    : boot

    " 부팅 디스크를 지정한다. 최대 세 개까지 명시가 가능하다. 명시 가능한 타입들은 `floppy`, `disk`, `cdrom`, `network`가 있다. 예시는 아래와 같다.

    boot: cdrom, floppy, disk ; 부팅 디스크에 대한 검사 순서를 지정한다. 즉, cdrom 검사하고 부팅 디스크가 아니면, floppy를 검사한다.
    boot: floppy
    boot: cdrom, disk
    boot: network, disk

     

     

    - 커맨드 라인 옵션

    : 대기중

     

     

    - 디버깅

    : BOCHS로 디버깅할 때, 처음에 당황스러운 점이 몇 가지 있다. `bochs -q`를 입력하면 `빠른 실행`이라고 해서 초반 메뉴 설정등을 생략하고 `bochsrc` 파일을 기준으로 동작한다. 그런데, 화면이 마치 정지한 것처럼 BOCHS는 멈춰있는 것 처럼 보인다. 거기서 프롬프트에 특정 키를 누를 수가 있는데, `c`를 누르면 GDB와 같이 끝까지 실행이 되버린다. `s`를 누르면, step으로 한 단계씩 나아각 된다. 근데, 여기서 문제가 있다. BOCHS는 최초 시작이 0x7C00이 아닌, BIOS 부터 시작한다. 그래서 `0xFFFFFFF0`에서 멈춰있게 된다. 이 위치는 x86 기반의 CPU가 파워온이 되면 제일 처음 명령어를 실행하는 위치다. 이 위치에 BIOS를 실행하는 명령어가 들어있다.

    ... bochs will break at the first instruction in the BIOS (not the bootloader nor the kernel). Notice that you won't be able to inspect kernel data at this point because your kernel has not yet been loaded by the bootloader ...

    - 참고 : https://www.cs.princeton.edu/courses/archive/fall09/cos318/precepts/bochs_gdb.html

     

     

    - 에러 사항

    : 디스크 파일과 이미지 파일 매칭 

    " BOCHS 설정 파일에 ATA 디바이스를 등록할 경우, CHS를 지정해야 한다. 이 계산법은 이 글을 참고하면 된다. BOCHS에서 제공하는 `bximage`를 유틸리티를 사용할 경우는 이런 문제가 없을 듯 한데, 그렇지 않을 경우, 이미지 파일과 동일한 사이즈의 C, H, S를 각각 제공해야 한다.

    이미지 파일 = C*H*S*512

    : 예를 들어, 이미지 파일 사이즈가 `264704` 일 경우, `512 * 11 * 47` 가 된다. 이 값이 `C * H * S * 512` 와 맵핑되어야 한다. 그렇면 `1 * 11 * 47 = C * H * S` 가 된다. 그리고 이미지 파일의 `C * H * S`를 구할 땐, 일단 512로 나눠야 한다.

     

    : 그런데, 각 속성마다 H는 16, S는 63 으로 MAX값이 존재한다. 그리고 이미지를 만들 때, 주의점이 있다. 이미지가 RAW 파일이여야 한다. 디스크 드라이브 드라이버들은 대게 이미지 파일 및 디스크 파일을 해석할 때, 정해진 포맷에 따라 해석한다. 그러나, BOCHS는 옛날 툴이라 그런지 RAW 파일만을 지원하는 듯 하다.

    ========================================================================
                            Bochs x86 Emulator 2.6
                Built from SVN snapshot on September 2nd, 2012
    ========================================================================
    00000000000i[     ] LTDL_LIBRARY_PATH not set. using compile time default '/usr/lib/bochs/plugins'
    00000000000i[     ] BXSHARE not set. using compile time default '/usr/share/bochs'
    00000000000i[     ] lt_dlhandle is 0x55f3ca782bf0
    00000000000i[PLGIN] loaded plugin libbx_unmapped.so
    00000000000i[     ] lt_dlhandle is 0x55f3ca784260
    00000000000i[PLGIN] loaded plugin libbx_biosdev.so
    00000000000i[     ] lt_dlhandle is 0x55f3ca785bd0
    00000000000i[PLGIN] loaded plugin libbx_speaker.so
    00000000000i[     ] lt_dlhandle is 0x55f3ca7863f0
    00000000000i[PLGIN] loaded plugin libbx_extfpuirq.so
    00000000000i[     ] lt_dlhandle is 0x55f3ca786bd0
    00000000000i[PLGIN] loaded plugin libbx_parallel.so
    00000000000i[     ] lt_dlhandle is 0x55f3ca788810
    00000000000i[PLGIN] loaded plugin libbx_serial.so
    00000000000i[     ] lt_dlhandle is 0x55f3ca78c5c0
    00000000000i[PLGIN] loaded plugin libbx_gameport.so
    00000000000i[     ] lt_dlhandle is 0x55f3ca78ce80
    00000000000i[PLGIN] loaded plugin libbx_iodebug.so
    00000000000i[     ] reading configuration from bochsrc
    00000000000i[     ] lt_dlhandle is 0x55f3ca78d7e0
    00000000000i[PLGIN] loaded plugin libbx_sdl.so
    00000000000i[     ] installing sdl module as the Bochs GUI
    00000000000i[     ] using log file bochsout.txt
    ========================================================================
    Event type: PANIC
    Device: [HD   ]
    Message: ata0-0: specified geometry doesn't fit on disk image

    A PANIC has occurred.  Do you want to:
      cont       - continue execution
      alwayscont - continue execution, and don't ask again.
                   This affects only PANIC events from device [HD   ]
      die        - stop execution now
      abort      - dump core 
      debug      - continue and return to bochs debugger
    Choose one of the actions above: [die]

     

    '프로젝트 > 운영체제 만들기' 카테고리의 다른 글

    [x86] Unreal mode  (0) 2023.06.28
    [x86] 멀티 부트  (0) 2023.06.27
    Long mode  (0) 2023.06.20
    [리눅스] - printf & printk  (0) 2023.06.19
    참고 자료  (0) 2023.06.14
Designed by Tistory.