많은 사람들이 컴퓨터가 어떻게 시작되는지에 관심이 있습니다. 마법이 시작되고 장치가 켜져 있는 동안 계속되는 곳입니다. 이 기사에서는 다양한 단계, 관련된 주요 구성 요소 및 프로세스 중에 직면하는 과제를 포함하여 부팅 프로세스에 대한 개요를 살펴보겠습니다.
우리의 주요 초점은 x86 아키텍처 (가장 널리 사용됨)에 있지만 다른 아키텍처는 부팅 프로세스에서 많은 유사점을 가지고 있습니다. 이 기사가 이 분야에 대한 지식을 심화시키려는 모든 사람에게 귀중한 자료가 되기를 바랍니다. 간다!
마더보드에 있고 컴퓨터 부팅을 담당하는 펌웨어 코드를 저장하는 집적 회로 (칩)를 BOOT ROM 이라고 합니다. 이 이름은 표준화되어 있지 않으므로 다른 개발자들은 FLASH ROM , BIOS FLASH , BOOT FLASH , SPI FLASH 등으로 부르는 경우가 많습니다(이러한 이름은 기술, 인터페이스 및 목적 이름 때문에 붙여진 것입니다). 걱정하지 마세요. 이 용어는 서로 바꿔서 사용할 수 있습니다. 컴퓨터 전원을 켜면 BOOT ROM 에 있는 펌웨어 코드가 가장 먼저 실행됩니다. 기본 테스트를 수행하고, 하드웨어를 초기화한 다음, 하드 드라이브나 USB 드라이브와 같은 부팅 가능한 장치에서 OS 로더를 메모리로 로드합니다. 이 칩은 비휘발성 메모리(NVM) 로 만들어졌습니다.
비휘발성 메모리는 전원이 꺼진 후에도 내용을 유지하는 컴퓨터 메모리 유형입니다. 이러한 유형의 메모리는 컴퓨터 전원이 꺼진 경우에도 유지되어야 하는 중요한 데이터를 저장하는 데 이상적입니다. 또한 논의는 펌웨어 코드를 보유하는 메모리에만 초점을 맞출 것입니다. 하드 디스크 드라이브(HDD), 솔리드 스테이트 드라이브(SSD), 플로피 디스크 등과 같은 스토리지에 대해서는 다루지 않습니다.
기본적으로 이러한 유형의 메모리를 다음 그룹으로 분류할 수 있습니다.
EEPROM(Electrically Erasable Programmable): 전기 신호를 사용하여 여러 번 다시 프로그래밍할 수 있습니다.
NOR 플래시 메모리 : 데이터가 블록 수준 에서 지워지고 바이트 수준 에서 읽거나 쓸 수 있는 블록으로 구조적으로 배열됩니다. NOR 메모리는 바이트 병렬, I2C 또는 SPI와 같은 표준 인터페이스를 사용하여 직접 액세스할 수 있습니다.
업계에서는 EEPROM 이라는 용어를 블록 단위 소거 가능 플래시 메모리와 비교하여 바이트 단위 소거 가능 메모리로 지정하는 관례가 있습니다.
프로그래밍 가능한 메모리에는 쓰기 전에 지우라는 한 가지 규칙이 있습니다. 이러한 메모리에서는 데이터가 플로팅 게이트에 전하로 저장되기 때문에 새로운 데이터를 쓰는 것이 더 복잡합니다. (대부분의 이유는 메모리 셀의 물리학에 있습니다.) 게이트의 전하량에 따라 셀이 "0" 또는 "1"을 저장할지 여부가 결정됩니다.
플래시 메모리 칩을 지우면 여기에 저장된 모든 데이터 비트가 알려진(기본) 상태, 일반적으로 논리 "1"로 설정됩니다. 이를 통해 말하자면 깨끗한 상태에서 시작하여 이전 데이터의 남은 부분을 칩에 저장하지 않고 칩에 새 데이터를 프로그래밍할 수 있습니다. 새로운 데이터가 칩에 기록되면 개별 비트의 상태가 "1"에서 "0"으로 변경되어 새로운 데이터를 나타냅니다.
칩을 먼저 지우지 않고 단순히 새 데이터를 칩에 쓰면 새 데이터가 이전 데이터와 결합되어 예측할 수 없는 결과가 발생합니다. 예를 들어, "0110 0010" 값을 저장하는 8비트 메모리를 가진 플래시 메모리 칩을 생각해 보세요. 칩을 먼저 지우지 않고 새 데이터 "1100 1001"을 칩에 쓰면 칩의 결과 상태는 "0100 0000"이 되며 이는 의도한 것과 다를 수 있습니다.
가장 큰 혼란은 읽기 전용 메모리(Read Only Memory)를 의미하는 ROM 이라는 단어와 관련이 있습니다. "읽기 전용 메모리"라는 용어는 역사적으로 영구적이고 사용자가 변경할 수 없는 메모리를 가리키는 데 사용되었습니다. 그러나 기술이 발전함에 따라 ROM의 정의가 바뀌었고 이제는 공장에서 미리 프로그래밍되어 최종 사용자가 쉽게 변경할 수 없는 메모리를 가리키는 데 종종 사용됩니다. 그러나 사용자가 원하는 기술과 전문 장비(예: 프로그래머)를 갖춘 경우 칩을 다시 프로그래밍할 수 있습니다. 정의가 변경되었음에도 불구하고 ROM이라는 이름은 메모리의 원래 목적에 대한 역사적 참조로 남아 있습니다.
쓰기 방지를 적용하면 일부 유형의 재프로그래밍 가능 ROM이 일시적으로 읽기 전용 메모리가 될 수 있습니다.
이것들은 기존의 모든 비휘발성 메모리 유형이 아니지만, 우연히 듣게 될 인기 있는 메모리 유형 중 대부분입니다. 요즘 대부분의 마더보드에서 이러한 칩은 NOR 플래시 기술을 사용하여 만들어집니다.
XIP(Execute in Place)는 프로세서가 휘발성 메모리(예: RAM )에 코드를 먼저 복사하지 않고 플래시 메모리에서 직접 코드를 실행할 수 있도록 하는 방법입니다. 이는 플래시 메모리를 프로세서의 주소 공간에 매핑하여 코드 실행이 플래시에서 직접 수행될 수 있도록 함으로써 달성됩니다. 따라서 시스템은 RAM이 먼저 초기화될 때까지 기다릴 필요 없이 최대한 빨리 코드 실행을 시작할 수 있습니다.
잠깐... CPU가 SPI/병렬/etc 프로토콜을 통해 BOOT ROM과 통신할 수 있나요? 물론 아닙니다. 시스템 메모리에서 명령을 가져오는 것뿐입니다. 이 메모리 영역에 대한 요청은 Intel Direct Media Interface(DMI ) 또는 AMD Infinity Fabric(IF) /Unified Media Interface(UMI)(이전 버전)로 리디렉션됩니다. CPU와 마더보드의 칩셋 사이를 연결하는 역할을 합니다. 이 시점에서 주소 디코딩은 칩셋에 있는 디코더를 통해 수행되고 칩의 데이터는 프로세서로 반환됩니다.
랜덤 액세스 읽기는 지원하지만 랜덤 액세스 쓰기는 지원하지 않는 NOR 플래시 메모리로 칩을 만들 때 한 가지 문제가 발생했습니다. 쓰기 가능한 메모리를 사용할 수 없는 한 모든 계산은 프로세서 레지스터 내에서 수행되어야 합니다. 이때 코드는 어셈블리 언어로만 작성할 수 있으며, 고급언어(보통 C언어 ) 환경을 구축하는 경향이 있다. 그 이유는 메모리 초기화가 너무 복잡해져서 순수하게 어셈블리로 작성하기가 어렵기 때문입니다. 이러한 언어에는 최소한 힙과 스택이 필요하므로 쓰기 가능한 메모리가 필요합니다. 일부 프로세서에는 칩 자체에 SRAM이 내장되어 있지만 보다 현대적인 접근 방식은 온보드 캐시 메모리를 CAR(RAM)로 사용하는 것입니다.
CPU 캐시는 메인 메모리에서 자주 사용하는 데이터와 명령의 복사본을 저장하는 고속 메모리입니다. 캐시는 프로세서에 더 가까이 위치하며 여러 수준(L1, L2, L3, ...)으로 구성되며, 각 수준은 이전 수준보다 크고 느립니다.
데이터가 캐시에 있으면 CPU는 캐시에서 요청된 데이터를 검색할 수 있습니다(이를 캐시 적중 이라고 함). CPU 캐시가 필요한 데이터를 찾을 수 없으면 캐시 미스가 발생합니다. 이는 데이터가 캐시에 저장되지 않았거나 데이터가 이전에 저장되었지만 캐시에서 제거 되었기 때문에 발생할 수 있습니다. 어쨌든 프로세서는 데이터에 액세스하고 이를 캐시에 복사하기 위해 주 메모리까지 가야 합니다.
캐시 제거는 새 데이터를 위한 공간을 확보하기 위해 캐시에서 데이터를 제거하는 프로세스입니다. 데이터 제거는 캐싱 시스템(일반적으로 캐시가 가득 차서 새 데이터를 저장해야 하는 경우 또는 데이터의 TTL(Time-To-Live) 정책이 만료된 경우) 또는 명시적인 요청에 의해 시작될 수 있습니다.
그러나 CPU 캐시를 RAM으로 사용하려면 캐시가 Non-Eviction Mode ( No-Fill 모드 라고도 함)에서 작동하도록 설정해야 합니다. 이 기술은 캐시 누락 으로 인한 제거를 방지합니다. 대신 캐시는 일반 SRAM으로 처리되며 모든 액세스(읽기/쓰기)는 캐시에 도달하고 주 메모리에는 도달 하지 않습니다 . 이 모드는 공급업체별 CPU 지침을 사용하여 활성화할 수 있습니다.
실제로 BOOT ROM에는 여러 유형의 펌웨어가 포함되어 있습니다. 일련의 펌웨어가 BOOT ROM에 저장되면 이를 구별하기 위해 어떻게든 구성해야 합니다. 그것이 어떻게 이루어지는지 알아봅시다.
원래 칩셋은 전체 BOOT ROM 내용을 메모리(4GB ~ 4GB - 16MB)에 직접 매핑합니다. 일반적으로 BOOT ROM이 16MB 미만인 경우 내용이 반복적으로 매핑됩니다. CPU와 펌웨어는 아무런 제한 없이 플래시를 읽고 쓸 수 있습니다.
Non-Descriptor 모드는 새로운 칩셋에서 더 이상 지원되지 않습니다.
결국 ICH8에서 Intel은 BOOT ROM을 위한 특별한 레이아웃을 도입했습니다. 플래시는 다음 영역으로 구분됩니다.
플래시 설명자(FD) - 이 데이터 구조는 0x10
오프셋으로 장치의 시작 부분에 위치해야 합니다. 아래 그림과 같이 11개의 섹션으로 구성됩니다.
설명자 MAP에는 다른 영역에 대한 포인터와 각 영역의 크기도 있습니다.
구성 요소 섹션에는 시스템의 플래시에 대한 정보(구성 요소 수, 각 밀도, 잘못된 지침 등)가 있습니다.
마스터 섹션에서는 지역에 대한 읽기/쓰기 권한을 정의합니다. 읽기/쓰기에 관한 한 권한은 읽기 전용으로 설정되어야 하며, 이 영역에 저장된 정보는 제조 프로세스 중에만 쓸 수 있습니다.
Flash Descriptor 와 Intel ME 는 유일한 필수 지역입니다.
FIT는 BIOS 영역 내부의 데이터 구조이며 플랫폼 구성을 설명하는 다양한 항목을 포함합니다. 테이블의 각 항목 크기는 16바이트입니다. 첫 번째는 FIT 헤더 라고 하고 다른 하나는 FIT 항목 이라고 합니다. 물리적 주소 0xFFFFFFC0
(4GB - 0x40)의 FIT 포인터 에 의해 위치합니다.
이러한 구성 요소는 재설정 벡터 에서 첫 번째 CPU 명령을 실행하기 전에 처리되어야 합니다. 항목에는 CPU 마이크로코드 업데이트, 시작 ACM, 플랫폼 부팅/TPM/BIOS/TXT 정책 및 기타 항목이 포함됩니다. 그러나 최소한 FIT에는 FIT 헤더 및 마이크로코드 업데이트 항목이 포함되어야 합니다. 따라서 FIT의 일반적인 사용법은 재설정 벡터를 실행하기 전에 마이크로코드를 업데이트하는 것입니다.
메모리 맵은 다음과 같습니다.
불행하게도 정보가 훨씬 적습니다. 레이아웃에 대한 세부 정보가 포함된 유출된 AMD 칩셋 문서를 찾을 수 없습니다. 따라서 coreboot 문서에서 말하는 것 보다 더 잘 말할 수는 없습니다. 이는 NDA에 의해서만 제공되는 AMD 문서를 기반으로 작성되었습니다.
실제로 플래시 설명자의 AMD 아날로그가 내장형 펌웨어 구조 이고 여기에 PSP 디렉토리 테이블 , BIOS 디렉토리 테이블 및 기타 펌웨어에 대한 포인터가 포함되어 있다는 사실만 알아도 충분합니다.
최신 메모리와 CPU가 정확히 어떻게 초기화되는지 알고 싶다면 당황스러울 것입니다. Intel과 AMD는 실리콘 초기화 코드를 커뮤니티에 공개하는 데 서두르지 않습니다. 그러한 정보가 공개적으로 제공되지 않는 한 필요한 실리콘 초기화 코드의 바이너리 배포를 제공합니다. 이는 펌웨어 개발자를 위한 라이브러리로 간주되며 메모리 컨트롤러, 칩셋, CPU 및 기타 시스템의 다른 부분을 초기화하는 바이너리 코드가 포함되어 있습니다.
해당 바이너리는 4가지 구성 요소로 나눌 수 있습니다.
다음은 Intel이 GitHub에서 찾을 수 있는 Intel FSP 바이너리의 리포지토리 입니다. FSP 사양 v2.1은 Intel 웹사이트에서 구할 수 있습니다.
Family 17h 이전 제품에 대한 AGESA는 v5 또는 Arch2008 로 알려져 있습니다. 당시 AGESA는 오픈 소스였으며 코드는 coreboot 저장소 에서 사용할 수 있었습니다(릴리스 4.18 이후에는 더 이상 사용되지 않음). Arch2008의 사양은 AMD 웹사이트에서 확인할 수 있습니다.
Family 17h (Zen 마이크로아키텍처) 제품이 출시됨에 따라 AMD는 AGESA 소스 코드를 게시하지 않았으며 사전 구축된 바이너리 솔루션만 게시했습니다. 이러한 후속 버전을 AGESA v9 라고 하며 Family 17h 이상을 지원합니다.
자세한 정보는 없고 뉴스 만 있습니다.
x86 코어가 활성화되지 않으면 최신 x86 부팅 프로세스의 필수 부분입니다. 따라서 완전히 비활성화하는 것은 불가능합니다 . 이러한 기술은 하드웨어 초기화, 시스템 무결성 확인, 전원 관리 및 CPU 실행을 담당합니다. 이러한 하위 시스템의 펌웨어는 메인 프로세서가 자체 펌웨어 실행을 시작하기 전에 로드되고 실행됩니다. 이러한 시스템의 코드는 플랫폼의 CPU 코어와 독립적으로 실행됩니다.
많은 하드웨어 회사가 모호함을 통해 보안 원칙을 통합하는 한 이러한 하위 시스템에 대한 소스 코드나 문서를 사용할 수 없습니다. 다행히도 이것이 부팅 프로세스에 어떤 영향을 미치는지 알고 있습니다. 하드웨어 전원 순서를 참조하세요.
이미 전 세계 연구자들의 광범위한 기사가 인터넷에 있기 때문에 자세히 설명하지 않겠습니다. 그러나 나는 그것이 무엇인지에 대해 간략하게 설명하겠습니다.
Intel ME는 2008년부터 Intel 칩셋(PCH)에 통합된 별도의 i486/80486 마이크로프로세서입니다. 자체 RAM, 내장 ROM, 칩셋 내부의 모든 버스에 대한 버스 브리지를 갖추고 있습니다(결과적으로 네트워크에 액세스할 수 있음). 심지어 CPU의 메인 RAM까지) 등이 있습니다. MINIX 기반의 맞춤형 OS를 실행합니다.
AMD PSP는 CPU 다이에 보조 프로세서로 삽입되는 Trustzone 확장을 사용하는 ARM 코어입니다. 이 칩은 2013년 이후 대부분의 AMD 플랫폼에 통합되었습니다. 문서화되지 않은 독점 OS를 실행합니다.
Power On Sequence 또는 Power Sequencing 이라고도 하는 이 프로세스는 플랫폼에 필요한 특정 순서로 파생된 여러 전압 레벨 및/또는 전원 공급 장치 레일을 제공합니다. 더 간단하게 말하면 특정 순서로 여러 플랫폼 구성 요소를 강화합니다. 프로세스는 시스템이나 플랫폼 설계에 따라 다르지만 일반적으로 표준 PC에는 다음 단계가 포함됩니다.
AMD 기반 시스템(Family 17h 이상용)
PSP는 온칩 BOOT ROM을 실행합니다.
PSP는 오프 칩 BOOT ROM에서 임베디드 펌웨어 테이블을 찾아 PSP 펌웨어를 실행합니다.
PSP는 PSP 디렉터리 테이블을 구문 분석하여 ABL 단계를 찾아 실행합니다.
ABL 단계에서는 주 메모리를 초기화하고, BOOT ROM에서 BIOS 이미지를 찾아 DRAM에 로드합니다(이미지가 압축된 경우 압축 해제).
이 플랫폼은 DRAM이 이미 사용 가능하고 PSP가 펌웨어 이미지를 CAR에 로드하기 때문에 CAR을 사용할 이유가 없습니다.
CPU의 전원을 처음 켠 후에는 리얼 모드 에서 작동합니다. 대부분의 레지스터에는 명령 포인터(IP), 코드 세그먼트(CS) 및 세그먼트 메모리에 대한 빠른 액세스를 허용하는 프로세서 내의 각 세그먼트 설명자의 복사 본인 설명자 캐시를 포함하여 잘 정의된 값이 있습니다.
세그먼트 설명자는 GDT(Global Descriptor Table) 의 항목이며 기본 주소, 세그먼트 제한 및 액세스 정보를 포함합니다(리얼 모드에는 보호 모드와 같은 액세스 제어가 없기 때문에 이 부분은 무시됩니다). 모든 메모리 액세스에 대해 GDT(메모리에 위치)에 액세스하는 대신 정보는 설명자 캐시에 저장됩니다.
그러나 GDT는 리얼 모드에 포함되지 않으므로 프로세서는 내부적으로 항목을 생성합니다. 세그먼트 설명자에 액세스하는 데 사용되는 CS 선택기 레지스터는 0xF000
으로 로드됩니다. CS 기본 주소는 0xFFFF_0000
으로 초기화됩니다. IP는 0xFFF0
으로 초기화됩니다.
따라서 프로세서는 물리적 주소 0xFFFF_FFF0
( 0xFFFF_0000
+ 0x0000_FFF0
)에 있는 메모리에서 명령을 가져오기 시작합니다. 해당 주소에서 실행되는 첫 번째 명령을 재설정 벡터 라고 합니다.
참고: 이 트릭을 사용하면 상위 주소 공간에 액세스할 수 있지만 0xFFFF_0000
주소 아래의 코드에는 액세스할 수 없습니다. CS 기본 주소는 CS 선택기 레지스터가 펌웨어에 의해 로드될 때까지 이 초기 값으로 유지됩니다. 멀리뛰기를 실행하면 가능합니다.
이 시점에서 가장 좋은 결정은 4GB의 주소 지정이 가능한 보호 모드로 전환하는 것입니다. 펌웨어가 이를 수행하지 않는 경우 리얼 모드가 작동하려면 칩셋은 1MB 미만의 메모리 범위를 4GB 미만의 해당 범위로 별칭을 지정할 수 있어야 합니다. 특정 칩셋에는 이러한 앨리어싱이 없으며 첫 번째 멀리뛰기를 수행하기 전에 다른 작동 모드로 전환해야 할 수도 있습니다.
ASUS P9X79 마더보드를 예로 들어 프로세스를 설명하는 전원 켜기 순서에 대한 아래 비디오를 시청하는 것이 좋습니다. 러시아어로 되어 있음에도 불구하고 자동 생성된 영어 자막을 켜면 모든 내용을 이해할 수 있습니다.
이 기사에서는 부팅 작동 방식과 관련된 많은 이론적 정보를 제공했습니다. 하지만 이 프로세스를 제대로 이해하려면 기존 펌웨어의 소스 코드와 아키텍처를 자세히 살펴볼 필요가 있습니다.
다음 기사에서는 BIOS , UEFI 및 coreboot 에 대해 자세히 알아보고 자세히 살펴보겠습니다.