안경잡이개발자

728x90
반응형

이 포스팅에는 부정확한 내용이 존재할 수 있습니다. Disk Identifier를 잘못 건드리면 파일 시스템에 문제가 생겨 부팅 자체에 실패할 수 있으며, 본 블로그의 글을 따라 하여 발생하는 문제에 대한 책임은 지지 않습니다.

 

※ 문제 상황 ※

 

  우리는 dd와 같은 명령어를 이용해 특정 디스크 내용 전체를 다른 디스크로 복제할 수 있다. 다만 이때 기본적으로 디스크(disk)의 식별자(identifier)도 복제된다. 만약 원본 디스크와 복제된 디스크를 둘 다 하나의 컴퓨터에 연결하여 부팅하게 되면 어떤 문제가 발생할 수 있을까? 다시 말해 디스크 식별자(disk identifier)가 완전히 동일한 두 개의 장치가 있을 때 부팅을 시도하는 것이다.

 

  이렇게 하면 UEFI를 위한 GPT가 올라가 있는 파티션Linux OS가 올라가 있는 파티션서로 다른 디스크(저장장치)로부터 인식하게 되는 문제가 발생할 수 있다.

 

  아래 그림은 SD 카드(mmcblk2)에 있는 디스크와 USB(sda)에 있는 디스크가 완전히 동일한 상황에서 부팅을 한 결과다. 분명히 SD 카드로 부팅을 시도했지만, GPT 부분만 정상적으로 SD 카드에 있는 파티션을 통해 인식했다. 실제로 리눅스(Linux) 파일 시스템에 대해서는 USB에 있는 파티션을 이용해 부팅을 진행한 것이다.

 

  즉, SD 카드로 부팅을 했는데 정작 USB에 있는 OS를 불러와 사용하고 있는 것이다. 디스크의 식별자가 동일하기 때문에 발생하는 문제다.

 

 

  만약에 SD 카드만 꽂혀 있거나, USB만 꽂혀 있는 경우에서는 당연히 정상적으로 하나의 디스크만 사용하여 부팅을 진행할 수 있다. 하지만 이처럼 동일한 식별자(identifier)를 가지는 두 개의 디스크가 동시에 꽂혀 있다면 OS를 부팅하는 과정에서 문제가 발생할 수 있다.

 

※ 문제의 원인 ※

 

  이러한 문제는 왜 발생하는 걸까? 앞서 말했듯이 디스크의 식별자가 동일하기 때문이다. 특히 GPT에 있는 GRUB과 관련이 있다. GRUB은 부트로더(bootloader)로서 불러올 OS가 존재하는 저장장치에 대한 정보를 환경설정 파일 형태로 미리 가지고 있을 수 있다.

 

  SD 카드로 부팅을 진행하게 되면, GPT 영역을 참조하여 미리 정해진 OS 파티션의 디스크로 실제 부팅을 진행한다. 이때 디스크 UUID가 중복되는 경우에는 UEFI 레벨에서 부팅하기로 설정한 저장장치(SD 카드)가 아닌 (USB와 같은) 다른 저장장치를 이용해 부팅을 진행할 수 있다는 것이다.

 

※ UUID 확인해 보기 ※

 

  이러한 문제를 해결하기 위해 하나의 디스크의 UUID를 변경하는 시도를 해보자. 그러기 전에 가장 먼저 blkid 명령어를 이용하여 UUID를 포함한 구체적인 저장장치 정보를 확인할 수 있다. (sudo blkid | grep UUID) 확인해 보면 sda와 mmcblk2p의 UUID가 정확히 동일한 것을 알 수 있다. 이러한 상황에서는 문제가 발생할 수 있는 것이다.

 

 

※ 해결 과정 ※

 

  문제를 해결하기까지 시도한 내용에 대하여 차근차근 명시하겠다.

 

[과정 1] tune2fs 명령어를 이용한 ext4 파티션 UUID 변경

 

  먼저 tune2fs에 대하여 알아보자. tune2fs는 리눅스 파일시스템의 다양한 변수 값을 바꿀 수 있도록 도와주는 명령어다. 한 번 OS가 존재하는 ext4 형식에 해당하는 /dev/mmcblk2p2 디바이스의 UUID를 변경해보겠다.

 

 

  성공적으로 변경된 것을 확인할 수 있다. /dev/mmcblk2p2의 UUID 부분이 새로운 값으로 변경되었다.

 

 

  이는 ext4 형식의 파일 시스템의 UUID를 변경하는 전형적인 방법이다. 또한, 이처럼 UUID를 변경하는 경우에는 fstab에서 이전 UUID 레이블(label) 정보를 가지고 있는지 확인할 필요가 있다. 따라서 UUID를 변경한 장치를 마운트한 뒤에 해당 UUID가 변경된 디바이스 내부의 /etc/fstab 파일을 열어서 ext4에 해당하는 UUID 값을 변경된 값에 맞게 수정해준다.

 

  이때 fstab파일시스템 정보를 담고 있는 설정 파일이다. 그러므로 부팅 시 UUID가 잘못 기록되어 있으면 grub까지만 진입하게 되며 OS를 정상적으로 부팅할 수 없게 된다.

 

 

  다만 여기까지 한다고 하더라도 재부팅을 진행했을 때 grub 단계에서 오류가 발생하고 OS 부팅으로 넘어가지 못하는 문제가 발생할 수 있다. 특히 필자의 경우 UUID를 바꾼 디바이스를 그 자체로 저장장치로 사용해야 하기 때문에 grub 단계에서 넘어가지 못하면 의미가 없었다.

 

[과정 2] grub.cfg 파일 수정

 

  말했듯이 fstab을 변경했다고 해도 여전히 grub 단계에서 다른 장치로 부팅을 시도하기 때문에, SD 카드로 부팅을 하였을 때 (USB 장치에서 OS를 불러오거나 하는) 오류가 발생할 수 있다. 따라서 grub 환경설정(configuration) 파일을 수정할 필요가 있다. 따라서 마찬가지로 UUID를 변경한 디바이스(device)를 마운트한 뒤에 /boot/grub/grub.cfg 파일을 수정한다.

 

  참고로 vi 에디터(editor)를 사용하면 다음과 같은 형식의 명령어를 이용해 문서 전체에서 특정 문자열을 다른 문자열로 바꿀 수 있다.

:%s/{변경할 문자열}/{변경 이후 문자열}/g


  필자는 다음과 같이 입력하여 일괄적으로 UUID를 변경했다.

:%s/6355c332-3454-4cbd-9a91-f4100bac43bf/fe0f0275-24f3-4a5c-8551-80ec4fa8cae7/g

 

  변경 결과는 다음과 같다. 이제 문서를 저장하고 나온다.

 

 

[과정 3] GPT 파티션의 grub.cfg 수정


  또한 GPT 파티션에도 이전 UUID 값이 기록되어 있는지 확인할 필요가 있다.

 

 

  그래서 필자는 UUID를 변경한 저장장치의 GPT 파티션을 마운트하여 /EFI/ubuntu/grub.cfg를 확인했다. 마찬가지로 여기에서도 UUID에 대한 값이 하드코딩되어 있었다. 그래서 이 값 또한 변경된 UUID가 들어갈 수 있도록 하였다.

 

 

  이제 마운트를 해제하고 재부팅을 진행한다. 그러면 정상적으로 SD 카드로 오류 없이 부팅이 완료된다. 참고로 여기까지의 과정을 수행하여 SD 카드와 USB를 완전히 구분할 수 있게 되었다는 것은, GPT 파티션의 UUID가 같아도 UEFI 레벨에서는 이 두 개를 구분할 수 있다는 의미가 된다.

 

[추가적인 시도] hexedit {/dev/example}

 

  그래도 아직 UEFI 관련 파티션의 UUID는 변경되지 않았다. 그래서 UEFI 파티션의 UUID를 바꾸기 위한 방법을 생각해 보다가 HEX 데이터를 변경하여 수정하는 방법을 진행해 보았다. UUID 값이 "EB93-49AC"라고 되어 있으므로, /를 눌러 "AC4993EB"를 검색했다.

 

 

이후에 해당 내용을 내가 원하는 문자열로 바꾸었다. 간단히 "12123434"로 바꾸어 볼 수 있을 것이다.

 

 

결과적으로 이번 시도에서는 다시 blkid 명령어를 사용했을 때 성공적으로 UUID가 변경된 것을 확인할 수 있었다.

 

 

  다만 이렇게 바꾸고 나서도 UEFI 레벨에서 저장장치의 UUID를 확인할 때는 여전히 변경되기 전의 UUID로 인식되고 있는 것을 알 수 있었다. 다시 말해 이 부분은 해결하지 못했다.

728x90
반응형

728x90
반응형

※ UEFI와 BIOS ※

 

  UEFI통합 확장 펌웨어 인터페이스(Unified Extensible Firmware Interface)의 줄임말입니다. UEFI를 이해하기 전에, 먼저 BIOS에 대해서 이해해야 합니다. BIOS란 기본 입출력 시스템 (Basic Input Output System)의 약자로, 일반적인 컴퓨터의 메인보드에 탑재되어 있는 펌웨어 소프트웨어입니다.

  ① 하드웨어② BIOS③ 부트 로더④ 운영체제(OS)⑤ 어플리케이션(App)

  일반적인 컴퓨터는 바로 위와 같이 계층적인 구조로 동작합니다.

 

  가장 먼저 우리가 컴퓨터의 전원을 눌러 전원을 공급하면, BIOS가 실행되어 컴퓨터의 하드웨어가 정상적인지 진단합니다. 이러한 하드웨어 검사를 흔히 POST(Power On Self Test)라고도 부릅니다. 흔히 컴퓨터를 조립할 때 메인 메모리(RAM) 없이 부팅을 하려고 하면 경고음이 몇 번 울리는 것 등이 그 예시입니다.

  이후에 부트 매니저(Boot Manager)가 실행됩니다. 흔히 컴퓨터 시작 직후에 [F2]를 연타하여 BIOS에 진입한 이후에 부트 디바이스를 설정할 수 있는데, 이러한 작업을 지원하는 것이 부트 매니저입니다. 이어서 선택한 부트 디바이스의 부트 로더가 실행됩니다. 여기에서 부트 로더(Boot Loader)란, 운영체제가 구동되기 이전에 미리 실행되어 운영체제가 올바르게 동작하기 위해 필요한 작업을 수행하는 소프트웨어를 말합니다. 예를 들어 윈도우(Windows) OS가 설치된 컴퓨터의 경우에는 윈도우가 1순위로 설정되어 실행되는 것을 떠올리시면 됩니다.

 

  UEFIBIOS를 대체하기 위해 등장한 시스템입니다. UEFI를 이용하는 경우 보안 부팅(Secure Booting)이 가능하며, BIOS에 비해서 더욱 큰 디스크 용량을 지원하고, 더욱 고급스러운 GUI를 제공하는 경우가 많습니다. 그래서 최근에 출시되는 컴퓨터 메인보드에는 기본적으로 UEFI가 탑재되어 출시되고 있습니다. 사용자 입장에서도 손쉽게 하드웨어를 조작할 수 있도록 해줍니다.

 

  사실 UEFI 자체는 명세서(Specification)입니다. 따라서 UEFI 규격에 맞게 개발된 펌웨어는 다양하게 존재할 수 있습니다. Tiano는 UEFI 규격을 따르는 최초의 오픈 소스 프로젝트인데, 이러한 Tiano에서 실질적으로 UEFI 구현체로 내보인 것이 바로 EDK입니다. 최근에는 EDK II 버전이 사용되고 있습니다. 즉 EDK II는 크로스 플랫폼을 지원하는 펌웨어 개발 환경(Firmware Development Environment)입니다. 기본적으로 UEFI 명세를 잘 따르고 있습니다.

 

  UEFI는 영문 위키(Wiki)에서도 잘 소개되고 있습니다.

 

  https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface

 

※ UEFI의 부팅 과정(Boot Flow) ※

 

  UEFI의 Boot Flow에 대해서 소개하고 있는 Tianocore 튜토리얼 페이지의 문서는 다음과 같습니다.

 

  https://github.com/tianocore/tianocore.github.io/wiki/PI-Boot-Flow

 

  UEFI의 부팅 과정은 크게 7단계로 구성됩니다.

728x90
반응형