Wednesday, November 16, 2005

Grub 옮기기

술 한잔 한 김에 꼬드겨서 Ubuntu linux 사용자를 한명 포섭했다.

펜3 700 시스템이니 윈도우 XP보다는 리눅스가 훨씬 빠르다고 얘기하니 망설임없이 그걸로 깔아보잔다. 즉각 설치에 돌입해서 깔끔한 X 화면을 보여주었다.

좀 사용해보더니 곧바로 묻는다.
"인터넷에서 동영상이 왜 안나와요?"
"인터넷 화면이 제대로 안 나오네요...."

역시 헛고생 한건가 싶은데 이렇게 말한다.
"그래도 리눅스 한번 써보고 싶었는데 그냥 놔두고요, 다른 하드를 하나 깔아서 XP를 듀얼로 쓸수있죠?"
"네....."

그 바람에 새 하드를 달고(slave로) 거기다 XP 깔려고 하니 MS 운영체계는 master에 최소한이라도 자기 파티션을 요구한다.
어쩔수 없이 새 하드를 master로 잡고 설치를 하고 나니 리눅스로 부팅하기가 난감이다.

ubuntu live CD로 부팅하기를 십여차례 한 끝에 살려서 듀얼 부팅을 할 수 있게 만들었다.

다음에 까먹지 않게 여기 남겨둬야 겠다.


1. 상황
Primary slave(/dev/hdb)에 이미 리눅스가 설치되어 있고 boot loader인 grub도 이 하드에 설치.
Primary master(/dev/hda)에 새로 ntfs 파티션을 만들어 윈도우 XP설치.

부팅하면 당연히 XP로만 부팅 됨.

파티션 정보는
/dev/hda1 ntfs

/dev/hdb1 ext3
/dev/hdb2 swap

2. 리눅스 복구 부팅
live CD로 부팅한 다음, 터미널을 뛰우고
리눅스가 설치된 파티션을 마운트
foo@bar:~$ sudo mkdir /temp
foo@bar:~$ sudo mount /dev/hdb1 /temp
root를 기존 리눅스 파티션으로 변경
foo@bar:~$ sudo chroot /temp

foo@bar:~# vi /etc/mtab
/dev/hda1 / ext3 rw,errors=remount-ro 0 0 에서 /dev/hda1 을 /dev/hdb1으로 수정

foo@bar:~# vi /etc/fstab
/dev/hda1 / ext3 defaults,errors=remount-ro 0 1
/dev/hda2 none swap sw 0 0
에서 각각 /dev/hda1 ==> /dev/hdb1 , /dev/hda2 ==> /dev/hdb2로 수정

foo@bar:~# cd /boot/grub
foo@bar:~# vi menu.lst
# menu.lst - See: grub(8), info grub, update-grub(8)
# grub-install(8), grub-floppy(8),
# grub-md5-crypt, /usr/share/doc/grub
# and /usr/share/doc/grub-doc/.

## default num
# Set the default entry to the entry number NUM. Numbering starts from 0, and
# the entry number 0 is the default if the command is not used.
#
# You can specify 'saved' instead of a number. In this case, the default entry
# is the entry saved with the command 'savedefault'.
default 0

## timeout sec
# Set a timeout, in SEC seconds, before automatically booting the default entry
# (normally the first entry defined).
timeout 10

## hiddenmenu
# Hides the menu by default (press ESC to see the menu)
#hiddenmenu

# Pretty colours
#color cyan/blue white/blue

## password ['--md5'] passwd
# If used in the first section of a menu file, disable all interactive editing
# control (menu entry editor and command-line) and entries protected by the
# command 'lock'
# e.g. password topsecret
# password --md5 $1$gLhU0/$aW78kHK1QfV3P2b2znUoe/
# password topsecret

#
# examples
#
# title Windows 95/98/NT/2000
# root (hd0,0)
# makeactive
# chainloader +1
#
# title Linux
# root (hd0,1)
# kernel /vmlinuz root=/dev/hda2 ro
#

#
# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST

### BEGIN AUTOMAGIC KERNELS LIST
## lines between the AUTOMAGIC KERNELS LIST markers will be modified
## by the debian update-grub script except for the default optons below

## DO NOT UNCOMMENT THEM, Just edit them to your needs

## ## Start Default Options ##
## default kernel options
## default kernel options for automagic boot options
## If you want special options for specifiv kernels use kopt_x_y_z
## where x.y.z is kernel version. Minor versions can be omitted.
## e.g. kopt=root=/dev/hda1 ro
# kopt=root=/dev/hda1 ro

## default grub root device
## e.g. groot=(hd0,0)
# groot=(hd0,0)

## should update-grub create alternative automagic boot options
## e.g. alternative=true
## alternative=false
# alternative=true

## should update-grub lock alternative automagic boot options
## e.g. lockalternative=true
## lockalternative=false
# lockalternative=false

## altoption boot targets option
## multiple altoptions lines are allowed
## e.g. altoptions=(extra menu suffix) extra boot options
## altoptions=(recovery mode) single
# altoptions=(recovery mode) single

## nonaltoption boot targets option
## This option controls options to pass to only the
## primary kernel menu item.
## You can have ONLY one nonaltoptions line
# nonaltoptions=quiet splash

## controls how many kernels should be put into the menu.lst
## only counts the first occurence of a kernel, not the
## alternative kernel options
## e.g. howmany=all
## howmany=7
# howmany=all

## should update-grub create memtest86 boot option
## e.g. memtest86=true
## memtest86=false
# memtest86=true

## ## End Default Options ##

title Ubuntu, kernel 2.6.10-5-386
root (hd0,0)
kernel /boot/vmlinuz-2.6.10-5-386 root=/dev/hda1 ro quiet splash
initrd /boot/initrd.img-2.6.10-5-386
savedefault
boot

title Ubuntu, kernel 2.6.10-5-386 (recovery mode)
root (hd0,0)
kernel /boot/vmlinuz-2.6.10-5-386 root=/dev/hda1 ro single
initrd /boot/initrd.img-2.6.10-5-386
savedefault
boot

title Ubuntu, kernel memtest86+
root (hd0,0)
kernel /boot/memtest86+.bin
savedefault
boot

### END DEBIAN AUTOMAGIC KERNELS LIST

무척 길기는 하지만 설치할 때 자동으로 생성된 파일이니 겁 먹을 거 없다.
빨간색으로 표시된 부분만 수정해 주면 된다.

title Windows XP //comment 표시인 #을 지워주고 제목 수정
root (hd0,0) //comment 표시인 #을 삭제
makeactive //comment 표시인 #을 삭제
chainloader +1 //comment 표시인 #을 삭제


title Ubuntu, kernel 2.6.10-5-386
root (hd0,0) ==> (hd1,0)로 변경
kernel /boot/vmlinuz-2.6.10-5-386 root=/dev/hda1 ro quiet splash
// /dev/hda1 을 /dev/hdb1으로 수정

initrd /boot/initrd.img-2.6.10-5-386
savedefault
boot

title Ubuntu, kernel 2.6.10-5-386 (recovery mode)
root (hd0,0) ==> (hd1,0)로 변경
kernel /boot/vmlinuz-2.6.10-5-386 root=/dev/hda1 ro single
// /dev/hda1 을 /dev/hdb1으로 수정
initrd /boot/initrd.img-2.6.10-5-386
savedefault
boot

title Ubuntu, kernel memtest86+
root (hd0,0) ==> (hd1,0)로 변경
kernel /boot/memtest86+.bin
savedefault
boot
수정사항을 저장한 다음
foo@bar:~# grub-install /dev/hda 해주면 된다.

만약 이때 /boot/grub/stage2 를 읽지 못한다는 에러메시지가 나온다면
이것은 grub-install 명령의 문제이다.

grub-install은 결국 grub의 옵션을 수행하는 wrapper 이므로 이때는
직접 grub을 실행해서 작업한다.

foo@bar:~# grub

grub> root (hd1,0)
Filesystem type is ext2fs, partition type 0x83

--> grub의 이미지가 있는 리눅스 루트가 /dev/hdb1이므로 hd1,0으로 정해준다.

어느 파티션에 이미지가 있는지를 모른다면 찾기 명령을 주면 된다.
grub> find /boot/grub/stage1
그 다음 설치를 한다.
grub> setup (hd0)

Checking if "/boot/grub/stage1" exists....... no
Checking if "/grub/stage1" exists....... yes
Checking if "/grub/stage2" exists....... yes
Checking if "/grub/e2fs_stage1_5" exists....... yes
Running "embed /grub/e2fs_stage1_5 (hd0)"....... 15 sectors are embedded
succeded
Running "install /grub/stage1 (hd0) (hd0) 1+15 p (hd0,2)/grub/stage2 /grub/grub.conf....... succeded
Done

-->이로써 grub을 hda의 MBR에 설치하는 것이 완료되었다.
grub> quit

아래는 grub설정에 관한 참고 내용이다.
알아도 그만 몰라도 그만일 수도 있다.

root (hd0,2)
Linux kernel image를 담고있는 /boot 파티션이 있는 곳. 그러므로 위의 설정은 GRUB에게 '커널은 첫번째 하드디스크의 세번째 파티션에 있다'고 알려주는 것이다.

apm=off acpi=on
power-off 명령이 정상적으로 작동되려면 커널에 알려주는것이 좋다.

initrd /initrd-2.4.22-1.2174.nptl.img
init ramdisk image가 있는 곳을 알려준다.

rootnoverify (hd0,0)
GRUB에게 Windows 파티션으로 부팅하지만 마운트하려고는 하지마라고 알려주는 것이다.
(hd0,0)는 Windows XP의 boot.ini가 있는 곳이다.

chainloader +1
chain-load는 다른 부트 로더를 띄워서 지원되지 않는 운영 체계를 올리기 위한 장치이다. 보통 DOS나 Windows를 띄우는데 쓴다.
GRUB에게 "chain to Windows' boot loader"라고 알려주는 것이다.


map
DOS (또는 Windows)가 첫번째 하드디스크에 설치되어 있지 않다면 disk swapping 기술이라는 것을 써야한다.
앞에서 처음 언급한 경우인데 윈도우 계열은 자신이 첫번째 하드에 있지않으면 부팅을 거부하기 때문이다. grub의 이 기능을 진작 알았더라면 일을 1/4로 줄일수 있었을 뻔 했다.

Map, 즉 어떤 드라이브를 다른 드라이브로 지정해주라는 말이다.

grub> map (hd0) (hd1)
grub> map (hd1) (hd0)

이렇게 준 명령은 첫번째와 두번째 하드디스크를 가상적으로 바꾸는 역할을 한다.

Caution: 이 명령은 오직 DOS (또는 Windows)가 바뀐 디스크에 접근하기 위해 BIOS 정보만을 이용할 경우에만 유효하다. 따로 드라이버가 필요한 경우에는 작동하지 않는다.

makeactive
root 디스크의 active 파티션을 GRUB의 root device로 지정한다. 하드디스크 상의 primary PC partition에만 해당된다. logical에는 해당되지 않음.

Code:
title Windows 98 SE
map (hd0) (hd1)
map (hd1) (hd0)
makeactive
rootnoverify (hd1,0)
chainloader +1


GRUB과 Linux 파티션의 관계

먼저, GRUB에서는 장치 이름이 괄호'( )'로 묶어져야 한다. 파티션 번호도 1이 아닌 0으로부터 시작됨을 명심해라.

GRUB의 장치 Linux의 장치명
(hd0) = hda
(hd1) = hdb
(hd0,1) = hda2
(hd0,4) = hda5
(hd1,0) = hdb1




GRUB images files

GRUB은 몇개의 이미지들로 구성된다: 두 개의 기본 stage들과 Stage 1.5로 불리는 추가 가능 이미지,두 개의 boot image 들이다.

'stage1' GRUB으로 부팅하게 하는 기본 이미지이. 보통 MBR 이나 파티션의 boot sector 에 설치(embeded)된다. PC boot sector가 512 bytes이므로, 이 image의 크기도 정확히 512 bytes이다. 'stage1'이 하는 역할은 로컬 디스크로부터 Stages 1.5의 Stage 2 를 띄우는 일이다. 크기 제한 때문에, 'stage1'은 BLOCK LIST FORMAT에서 Stage 2 (or Stage 1.5)의 위치를 인코딩하므로,어떠한 filesystem 구조도 이해하지 못한다.

'stage2' 가 GRUB의 core image이다. 자신으로 부팅하는 것 빼고는 모든걸 한다. 보통 filesystem에 쓰여지지만, 안 그래도 된다.

'e2fs_stage1_5'
'fat_stage1_5'
'ffs_stage1_5'
'jfs_stage1_5'
'minix_stage1.5'
'reiserfs_stage1.5'
'vstafs_stage1.5'
'xfs_stage1_5'
이것들이 Stage 1.5 라고 불리는 것 들인데 'stage1''stage2'사이를 이어주기 때문이다. 다시말해, Stage 1.5는 Stage 1에 의해 띄워지며 Stage 2를 띄운다. 'stage1''*_stage1_5'의 차이는 전자가 파일시스템은 알수없지만 후자는 하나의 파일시스템을 이해한다는 것이다 (예. 'e2fs_stage1_5'는 ext2fs를 인식). 그러므로 Stage 2 image를 다른 곳으로 옮길 수 있는 것이다.
Stage 2의 크기가 커서 통상적으로 고정적 구역에 설치(embedded)되지 못하지만, Stage 1.5 는 MBR 바로 뒤나 ReiserFS 또는 FFS의 부트 로더 영역에 설치될 수 있다.

'nbgrub' 이것은 network boot image이며 Etherboot 등과 같은 네트웍 부트 로더가 사용하는 Network Image Proposal을 위한 것이다. Stage2와 거의 같으나 네트웍을 설정하고 네트웍으로부터 설정 파일을 띠운다.

'pxegrub' 일부 Netboot ROM들을 위한 Preboot Execution Environment와 같은 데서 사용하는 또다른 네트웍 부트 이미지이다. 포맷을 제외하면 'nbgrub'과 똑같다.

GRUB boot floppy 만들기

GRUB boot floppy를 만들려면 이미지 디렉토리의 'stage1''stage2' 이 있어야 한다. 이 파일들을 플로피의 첫번째와 두번째 블럭에 각각 기록한다:


Code:
cd /usr/share/grub/i386-redhat
dd if=stage1 of=/dev/fd0 bs=512 count=1
dd if=stage2 of=/dev/fd0 bs=512 seek=1


GRUB을 플로피에 설치
Code:
# /sbin/grub-install /dev/fd0

Quote:
# /sbin/grub-install /dev/fd0
Installation finished. No error reported.
This is the contents of the device map /boot/grub/device.map.
Check if this is correct or not. If any of the lines is incorrect,
fix it and re-run the script `grub-install'.

# this device map was generated by anaconda
(fd0) /dev/fd0
(hd0) /dev/hda
새로운 커널을 설치할 때마다 플로피 이미지도 업데이트 해주어야 한다.
"/sbin/grub-install /dev/fd0" 을 다시 실행하라.

No comments: