

# 使用 Amazon EC2 启动模式的实例启动行为
<a name="ami-boot"></a>

电脑启动时，它运行的第一个软件负责初始化平台并为操作系统执行特定于平台的操作提供界面。

在 Amazon EC2 中，支持启动模式软件的两种变体包括：统一可扩展固件接口（UEFI）和传统 BIOS。

**AMI 上可能的启动模式参数**  
AMI 可以具有以下任一启动模式参数值：`uefi`、`legacy-bios` 或 `uefi-preferred`。AMI 启动模式参数是可选项。对于不带启动模式参数的 AMI，从这些 AMI 启动的实例将使用实例类型的默认启动模式值。

**AMI 启动模式参数的用途**  
AMI 启动模式参数向 Amazon EC2 发出信号，指明启动实例时要使用哪种启动模式。当启动模式参数设置为 `uefi` 时，EC2 将尝试在 UEFI 上启动实例。如果操作系统未配置为支持 UEFI，则实例启动可能失败。

**UEFI Preferred 启动模式参数**  
您可以使用 `uefi-preferred` 启动模式参数创建同时支持 UEFI 和传统 BIOS 的 AMI。当启动模式参数设置为 `uefi-preferred` 并且实例类型支持 UEFI 时，实例会在 UEFI 上启动。如果实例类型不支持 UEFI，实例会在传统 BIOS 上启动。

**警告**  
UEFI 安全启动等部分功能仅适用于在 UEFI 上启动的实例。将 `uefi-preferred` AMI 启动模式参数与不支持 UEFI 的实例类型结合使用时，实例将以传统 BIOS 启动，并禁用 UEFI 相关功能。如果您依赖于 UEFI 相关功能的可用性，请将 AMI 启动模式参数设置为 `uefi`。

**实例类型的默认启动模式**
+ Graviton 实例类型：UEFI
+ Intel 和 AMD 实例类型：传统 BIOS

**区域支持**  
Wavelength 区中不支持 UEFI 启动。

**Topics**
+ [在 UEFI 启动模式下启动 EC2 实例的要求](launch-instance-boot-mode.md)
+ [确定 Amazon EC2 AMI 的启动模式参数](ami-boot-mode.md)
+ [确定 EC2 实例类型支持的启动模式](instance-type-boot-mode.md)
+ [确定 EC2 实例的启动模式](instance-boot-mode.md)
+ [确定 EC2 实例操作系统的启动模式](os-boot-mode.md)
+ [设置 Amazon EC2 AMI 的启动模式](set-ami-boot-mode.md)
+ [Amazon EC2 实例的 UEFI 变量](uefi-variables.md)
+ [适用于 Amazon EC2 实例的 UEFI 安全启动](uefi-secure-boot.md)

# 在 UEFI 启动模式下启动 EC2 实例的要求
<a name="launch-instance-boot-mode"></a>

实例的启动模式由 AMI 的配置、其中包含的操作系统和实例类型决定。要在 UEFI 启动模式下启动实例，必须满足以下要求。

**AMI**  
AMI 必须按如下方式为 UEFI 配置：  
+ **操作系统** – AMI 中包含的操作系统必须配置为使用 UEFI；否则，实例启动将失败。有关更多信息，请参阅 [确定 EC2 实例操作系统的启动模式](os-boot-mode.md)。
+ **AMI 启动模式参数** – AMI 的启动模式参数必须设置为 `uefi` 或 `uefi-preferred`。有关更多信息，请参阅 [确定 Amazon EC2 AMI 的启动模式参数](ami-boot-mode.md)。
**Linux** – 以下 Linux AMI 支持 UEFI：  
+ Amazon Linux 2023
+ Amazon Linux 2（仅适用于 Graviton 实例类型）
至于其他 Linux AMI，则必须[配置 AMI](set-ami-boot-mode.md)，通过 [VM Import/Export](https://docs.aws.amazon.com/vm-import/latest/userguide/) 导入 AMI，或通过 [CloudEndure](https://docs.cloudendure.com/) 导入 AMI。  
**Windows**：以下 Windows AMI 支持 UEFI：  
+ Windows\$1Server-2025-\$1（带有 `BIOS-` 名称前缀的 AMI 除外）
+ TPM-Windows\$1Server-2022-English-Full-Base
+ TPM-Windows\$1Server-2022-English-Core-Base
+ TPM-Windows\$1Server-2019-English-Full-Base
+ TPM-Windows\$1Server-2019-English-Core-Base
+ TPM-Windows\$1Server-2016-English-Full-Base
+ TPM-Windows\$1Server-2016-English-Core-Base

**实例类型**  
所有基于 AWS Nitro System 构建的实例都支持 UEFI 和传统 BIOS，下列实例除外：裸机实例、DL1、G4ad、P4、u-3tb1、u-6tb1、u-9tb1、u-12tb1、u-18tb1、u-24tb1 和 VT1。有关更多信息，请参阅 [确定 EC2 实例类型支持的启动模式](instance-type-boot-mode.md)。

下表显示，实例的启动模式（由**生成的实例启动模式**列表示）由 AMI 的启动模式参数（第 1 列）、AMI 中包含的操作系统的启动模式配置（第 2 列）和实例类型的启动模式支持（第 3 列）共同决定。


| AMI 启动模式参数 | 操作系统启动模式配置 | 实例类型启动模式支持 | 生成的实例启动模式 | 
| --- | --- | --- | --- | 
| UEFI | UEFI | UEFI | UEFI | 
| 传统 BIOS | 传统 BIOS | 传统 BIOS | 传统 BIOS | 
| UEFI Preferred | UEFI | UEFI | UEFI | 
| UEFI Preferred | UEFI | UEFI 和传统 BIOS | UEFI | 
| UEFI Preferred | 传统 BIOS | 传统 BIOS | 传统 BIOS | 
| UEFI Preferred | 传统 BIOS | UEFI 和传统 BIOS | 传统 BIOS | 
| 未指定启动模式 – ARM | UEFI | UEFI | UEFI | 
| 未指定启动模式 – x86 | 传统 BIOS | UEFI 和传统 BIOS | 传统 BIOS | 

# 确定 Amazon EC2 AMI 的启动模式参数
<a name="ami-boot-mode"></a>

AMI 启动模式参数是可选项。AMI 可以具有以下任一启动模式参数值：`uefi`、`legacy-bios` 或 `uefi-preferred`。

某些 AMI 没有启动模式参数。如果 AMI 没有启动模式参数，从 AMI 启动的实例将使用实例类型的默认值，在 Graviton 上使用 `uefi`，并在 Intel 和 AMD 实例类型上使用 `legacy-bios`。

------
#### [ Console ]

**确定 AMI 的启动模式参数**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择 **AMI**，然后选择 AMI。

1. 检查**启动模式**字段。
   + 值 **uefi** 表示 AMI 支持 UEFI。
   + 值 **uefi-preferred** 表示 AMI 同时支持 UEFI 和传统 BIOS。
   + 如果没有值，从 AMI 启动的实例将使用实例类型的默认值。

**在启动实例时确定 AMI 的启动模式参数**  
使用启动实例向导启动实例时，请在选择 AMI 的步骤中检查**启动模式**字段。有关更多信息，请参阅 [应用程序和操作系统映像（亚马逊机器映像）](ec2-instance-launch-parameters.md#liw-ami)。

------
#### [ AWS CLI ]

**确定 AMI 的启动模式参数**  
使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html) 命令确定 AMI 的启动模式。

```
aws ec2 describe-images \
    --region us-east-1 \
    --image-id ami-0abcdef1234567890 \
    --query Images[].BootMode \
    --output text
```

下面是示例输出。

```
uefi
```

输出中的值 `uefi` 表示 AMI 支持 UEFI。值 `uefi-preferred` 表示 AMI 同时支持 UEFI 和传统 BIOS。如果没有值，从 AMI 启动的实例将使用实例类型的默认值。

------
#### [ PowerShell ]

**确定 AMI 的启动模式参数**  
使用 [https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Image.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Image.html) cmdlet 确定 AMI 的启动模式。

```
Get-EC2Image -Region us-east-1 `
    -ImageId ami-0abcdef1234567890 | Format-List Name, BootMode, TpmSupport
```

下面是示例输出。

```
Name       : TPM-Windows_Server-2016-English-Full-Base-2023.05.10
BootMode   : uefi
TpmSupport : v2.0
```

输出中的值 `BootMode` 表示 AMI 的启动模式。值 `uefi` 表示 AMI 支持 UEFI。值 `uefi-preferred` 表示 AMI 同时支持 UEFI 和传统 BIOS。如果没有值，从 AMI 启动的实例将使用实例类型的默认值。

------

# 确定 EC2 实例类型支持的启动模式
<a name="instance-type-boot-mode"></a>

您可以确定实例类型支持的启动模式。

Amazon EC2 控制台不会显示实例类型支持的启动模式。

------
#### [ AWS CLI ]

使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instance-types.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instance-types.html) 命令确定实例类型支持的启动模式。`--query` 参数筛选输出以仅返回支持的启动模式。

以下示例显示，指定的实例类型同时支持 UEFI 和传统 BIOS 启动模式。

```
aws ec2 describe-instance-types \
    --instance-types m5.2xlarge \
    --query "InstanceTypes[*].SupportedBootModes"
```

下面是示例输出。

```
[
    [
        "legacy-bios",
        "uefi"
    ]
]
```

以下示例显示 `t2.xlarge` 仅支持传统 BIOS。

```
aws ec2 describe-instance-types \
    --instance-types t2.xlarge \
    --query "InstanceTypes[*].SupportedBootModes"
```

下面是示例输出。

```
[
    [
        "legacy-bios"
    ]
]
```

------
#### [ PowerShell ]

使用 [https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceType.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceType.html) cmdlet 确定实例类型支持的启动模式。

以下示例显示 `m5.2xlarge` 支持 UEFI 和传统 BIOS 启动模式。

```
Get-EC2InstanceType -InstanceType m5.2xlarge | Format-List InstanceType, SupportedBootModes
```

下面是示例输出。

```
InstanceType       : m5.2xlarge
SupportedBootModes : {legacy-bios, uefi}
```

以下示例显示 `t2.xlarge` 仅支持传统 BIOS。

```
Get-EC2InstanceType -InstanceType t2.xlarge | Format-List InstanceType, SupportedBootModes
```

下面是示例输出。

```
InstanceType       : t2.xlarge
SupportedBootModes : {legacy-bios}
```

------

**确定支持 UEFI 的实例类型**  
您可以确定支持 UEFI 的实例类型。Amazon EC2 控制台不会显示实例类型是否支持 UEFI。

------
#### [ AWS CLI ]

可用的实例类型因 AWS 区域 而异。要查看某个区域中支持 UEFI 的可用实例类型，请使用 [describe-instance-types](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instance-types.html) 命令。包括 `--filters` 参数以将结果范围限定为支持 UEFI 的实例类型，并包括 `--query` 参数以将输出范围限定为 `InstanceType` 的值。

```
aws ec2 describe-instance-types \
    --filters Name=supported-boot-mode,Values=uefi \
    --query "InstanceTypes[*].[InstanceType]" --output text | sort
```

------
#### [ PowerShell ]

可用的实例类型因 AWS 区域 而异。要查看某个区域中支持 UEFI 的可用实例类型，请使用 [Get-EC2InstanceType](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceType.html) cmdlet。

```
Get-EC2InstanceType | `
	Where-Object {$_.SupportedBootModes -Contains "uefi"} | `
	Sort-Object InstanceType | `
	Format-Table InstanceType -GroupBy CurrentGeneration
```

------

**确定支持 UEFI 安全启动并保留非易失性变量的实例类型**  
裸机实例不支持 UEFI 安全启动和非易失性变量，因此这些示例将它们从输出中排除。有关 UEFI 安全启动的信息，请参阅 [适用于 Amazon EC2 实例的 UEFI 安全启动](uefi-secure-boot.md)。

------
#### [ AWS CLI ]

使用 [describe-instance-types](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instance-types.html) 命令，并从输出中排除裸机实例。

```
aws ec2 describe-instance-types \
    --filters Name=supported-boot-mode,Values=uefi Name=bare-metal,Values=false \
    --query "InstanceTypes[*].[InstanceType]" \
    --output text | sort
```

------
#### [ PowerShell ]

使用 [Get-EC2InstanceType](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceType.html) cmdlet，并从输出中排除裸机实例。

```
Get-EC2InstanceType | `
    Where-Object { `
        $_.SupportedBootModes -Contains "uefi" -and `
        $_.BareMetal -eq $False
        } | `
    Sort-Object InstanceType  | `
    Format-Table InstanceType, SupportedBootModes, BareMetal, `
        @{Name="SupportedArchitectures"; Expression={$_.ProcessorInfo.SupportedArchitectures}}
```

------

# 确定 EC2 实例的启动模式
<a name="instance-boot-mode"></a>

实例的启动模式会在 Amazon EC2 控制台中的**启动模式**字段中，通过 AWS CLI 中的 `currentInstanceBootMode` 参数显示。

启动实例时，其启动模式参数的值由启动该实例所用的 AMI 的启动模式参数的值决定，如下所示：
+ 启动模式参数为 `uefi` 的 AMI 会创建 `currentInstanceBootMode` 参数为 `uefi` 的实例。
+ 启动模式参数为 `legacy-bios` 的 AMI 会创建 `currentInstanceBootMode` 参数为 ` legacy-bios` 的实例。
+ 如果实例类型支持 UEFI，则启动模式参数为 `uefi-preferred` 的 AMI 会创建 `currentInstanceBootMode` 参数为 `uefi` 的实例；否则将创建 `currentInstanceBootMode` 参数为 `legacy-bios` 的实例。
+ 没有启动模式参数值的 AMI 会创建参数值为 `currentInstanceBootMode` 的实例，该值取决于 AMI 架构是 ARM 还是 x86，以及实例类型支持哪种启动模式。Graviton 实例类型上的默认启动模式为 `uefi`，而 Intel 和 AMD 实例类型上的默认启动模式为 `legacy-bios`。

------
#### [ Console ]

**确定实例的启动模式**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择 **Instances (实例)**，然后选择您的实例。

1. 在**详细信息**选项卡上，检查**启动模式**字段。

------
#### [ AWS CLI ]

**确定实例的启动模式**  
使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html) 命令确定实例的启动模式。您还可以确定用于创建实例的 AMI 的启动模式。

```
aws ec2 describe-instances \
    --region us-east-1 \
    --instance-ids i-1234567890abcdef0 \
    --query Reservations[].Instances[].BootMode \
    --output text
```

下面是示例输出。

```
uefi
```

------
#### [ PowerShell ]

**确定实例的启动模式**  
使用 [https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Instance.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Instance.html) cmdlet 确定实例的启动模式。您还可以确定用于创建实例的 AMI 的启动模式。

```
(Get-EC2Instance `
    -InstanceId i-1234567890abcdef0).Instances | Format-List BootMode, CurrentInstanceBootMode, InstanceType, ImageId
```

下面是示例输出。

```
BootMode                : uefi
CurrentInstanceBootMode : uefi
InstanceType            : c5a.large
ImageId                 : ami-0abcdef1234567890
```

------

# 确定 EC2 实例操作系统的启动模式
<a name="os-boot-mode"></a>

AMI 的启动模式指导 Amazon EC2 使用哪种启动模式来启动实例。要查看实例的操作系统是否配置为 UEFI，需要通过 SSH（Linux 实例）或 RDP（Windows 实例）连接到实例。

请使用适用于您实例操作系统的说明。

## Linux
<a name="os-boot-mode-linux"></a>

**要确定实例操作系统的启动模式**

1. [使用 SSH 连接到 Linux 实例](connect-linux-inst-ssh.md)。

1. 要查看操作系统的启动模式，请尝试以下任一操作：
   + 运行如下命令。

     ```
     [ec2-user ~]$ sudo /usr/sbin/efibootmgr
     ```

     在 UEFI 启动模式下启动的实例的预期输出

     ```
     BootCurrent: 0001
     Timeout: 0 seconds
     BootOrder: 0000,0001
     Boot0000* UiApp
     Boot0001* UEFI Amazon Elastic Block Store vol-xyz
     ```
   + 运行以下命令以验证 `/sys/firmware/efi` 目录是否存在。仅当实例使用 UEFI 启动时，此目录才会存在。如果此目录不存在，该命令将返回 `Legacy BIOS Boot Detected`。

     ```
     [ec2-user ~]$ [ -d /sys/firmware/efi ] && echo "UEFI Boot Detected" || echo "Legacy BIOS Boot Detected"
     ```

     在 UEFI 启动模式下启动的实例的预期输出

     ```
     UEFI Boot Detected
     ```

     在传统 BIOS 启动模式下启动的实例的预期输出

     ```
     Legacy BIOS Boot Detected
     ```
   + 运行以下命令以验证 EFI 是否出现在 `dmesg` 输出中。

     ```
     [ec2-user ~]$ dmesg | grep -i "EFI"
     ```

     在 UEFI 启动模式下启动的实例的预期输出

     ```
     [    0.000000] efi: Getting EFI parameters from FDT:
     [    0.000000] efi: EFI v2.70 by EDK II
     ```

## Windows
<a name="os-boot-mode-windows"></a>

**要确定实例操作系统的启动模式**

1. [使用 RDP 连接到 Windows 实例](connecting_to_windows_instance.md)。

1. 转到**系统信息**并检查 **BIOS 模式**行。  
![\[显示所选 BIOS 模式行的系统信息窗口。BIOS 模式的值为 Legacy。\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/images/BIOS-mode-win.png)

# 设置 Amazon EC2 AMI 的启动模式
<a name="set-ami-boot-mode"></a>

默认情况下，AMI 会继承用于创建 AMI 的 EC2 实例的启动模式。例如，如果从传统 BIOS 上运行的 EC2 实例创建 AMI，则新 AMI 的启动模式为 `legacy-bios`。如果从启动模式为 `uefi-preferred` 的 EC2 实例创建 AMI，则新 AMI 的启动模式为 `uefi-preferred`。

注册 AMI 时，可以将 AMI 的启动模式设置为 `uefi`、`legacy-bios` 或 `uefi-preferred`。

当 AMI 启动模式设置为 `uefi-preferred` 时，实例将按如下方式启动：
+ 对于同时支持 UEFI 和传统 BIOS 的实例类型（例如 `m5.large`），实例通过 UEFI 启动。
+ 对于仅支持传统 BIOS 的实例类型（例如 `m4.large`），实例通过传统 BIOS 启动。

如果将 AMI 启动模式设置为 `uefi-preferred`，则操作系统必须支持同时启动 UEFI 和传统 BIOS 的功能。

要将现有的基于传统 BIOS 的实例转换为 UEFI，或将现有的基于 UEFI 的实例转换为传统 BIOS，必须首先修改实例的卷和操作系统以支持选定的启动模式。然后，创建该卷的快照。首先，从快照创建 AMI。

**注意事项**
+ 设置 AMI 启动模式参数不会自动将操作系统配置为指定的启动模式。您必须首先对实例的卷和操作系统进行适当的修改，以支持通过选定的启动模式启动。否则，生成的 AMI 将不可用。例如，如果要将基于传统 BIOS 的 Windows 实例转换为 UEFI，则可以使用 Microsoft 的 [MBR2GPT](https://learn.microsoft.com/en-us/windows/deployment/mbr-to-gpt) 工具将系统磁盘从 MBR 转换为 GPT。所需的修改是特定于操作系统的。有关更多信息，请参阅操作系统的手册。
+ 无法使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html) 命令或 [https://docs.aws.amazon.com/powershell/latest/reference/items/Register-EC2Image.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Register-EC2Image.html) cmdlet 创建同时支持 [NitroTPM](nitrotpm.md) 和 UEFI Preferred 的 AMI。
+ UEFI 安全启动等部分功能仅适用于在 UEFI 上启动的实例。将 `uefi-preferred` AMI 启动模式参数与不支持 UEFI 的实例类型结合使用时，实例将以传统 BIOS 启动，并禁用 UEFI 相关功能。如果您依赖于 UEFI 相关功能的可用性，请将 AMI 启动模式参数设置为 `uefi`。

------
#### [ AWS CLI ]

**设置 AMI 的启动模式**

1. 对实例的卷和操作系统进行适当的修改，以支持通过选定的启动模式启动。所需的修改是特定于操作系统的。有关更多信息，请参阅操作系统的手册。
**警告**  
如果不执行此步骤，AMI 将无法使用。

1. 要查找实例的卷 ID，请使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html) 命令。您将在下一步中创建此卷的快照。

   ```
   aws ec2 describe-instances \
       --instance-ids i-1234567890abcdef0 \
       --query Reservations[].Instances[].BlockDeviceMappings
   ```

   下面是示例输出。

   ```
   [
       [
           {
               "DeviceName": "/dev/xvda",
               "Ebs": {
                   "AttachTime": "2024-07-11T01:05:51+00:00",
                   "DeleteOnTermination": true,
                   "Status": "attached",
                   "VolumeId": "vol-1234567890abcdef0"
               }
           }
       ]
   ]
   ```

1. 要创建卷的快照，请使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/create-snapshot.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-snapshot.html) 命令。使用上一步中的卷 ID。

   ```
   aws ec2 create-snapshot \
       --volume-id vol-01234567890abcdef \
       --description "my snapshot"
   ```

   下面是示例输出。

   ```
   {
       "Description": "my snapshot",
       "Encrypted": false,
       "OwnerId": "123456789012",
       "Progress": "",
       "SnapshotId": "snap-0abcdef1234567890",
       "StartTime": "",
       "State": "pending",
       "VolumeId": "vol-01234567890abcdef",
       "VolumeSize": 30,
       "Tags": []
   }
   ```

1. 等到快照状态为 `completed` 后，继续执行下一步。要获取快照状态，请将 [https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-snapshots.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-snapshots.html) 命令与上一步中的快照 ID 结合使用。

   ```
   aws ec2 describe-snapshots \
       --snapshot-ids snap-0abcdef1234567890 \
       --query Snapshots[].State \
       --output text
   ```

   下面是示例输出。

   ```
   completed
   ```

1. 要创建新的 AMI，请使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html) 命令。使用 **CreateSnapshot** 输出中 `SnapshotId` 的值。
   + 要将启动模式设置为 UEFI，请添加 `--boot-mode` 参数，并指定值 `uefi`。

     ```
     aws ec2 register-image \
        --description "my image" \
        --name "my-image" \
        --block-device-mappings "DeviceName=/dev/sda1,Ebs={SnapshotId=snap-0abcdef1234567890,DeleteOnTermination=true}" \
        --root-device-name /dev/sda1 \
        --virtualization-type hvm \
        --ena-support \
        --boot-mode uefi
     ```
   + 要将启动模式设置为 `uefi-preferred`，请将 `--boot-mode` 的值设置为 `uefi-preferred`

     ```
     aws ec2 register-image \
        --description "my description" \
        --name "my-image" \
        --block-device-mappings "DeviceName=/dev/sda1,Ebs={SnapshotId=snap-0abcdef1234567890,DeleteOnTermination=true}" \
        --root-device-name /dev/sda1 \
        --virtualization-type hvm \
        --ena-support \
        --boot-mode uefi-preferred
     ```

1. （可选）要验证新创建的 AMI 是否具有您指定的启动模式，请使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html) 命令。

   ```
   aws ec2 describe-images \
       --image-id ami-1234567890abcdef0 \
       --query Images[].BootMode \
       --output text
   ```

   下面是示例输出。

   ```
   uefi
   ```

------
#### [ PowerShell ]

**设置 AMI 的启动模式**

1. 对实例的卷和操作系统进行适当的修改，以支持通过选定的启动模式启动。所需的修改是特定于操作系统的。有关更多信息，请参阅操作系统的手册。
**警告**  
如果不执行此步骤，AMI 将无法使用。

1. 要查找实例的卷 ID，请使用 [https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Instance.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Instance.html) cmdlet。

   ```
   (Get-EC2Instance `
       -InstanceId i-1234567890abcdef0).Instances.BlockDeviceMappings.Ebs
   ```

   下面是示例输出。

   ```
   AssociatedResource  : 
   AttachTime          : 7/11/2024 1:05:51 AM
   DeleteOnTermination : True
   Operator            : 
   Status              : attached
   VolumeId            : vol-01234567890abcdef
   ```

1. 要创建卷的快照，请使用 [https://docs.aws.amazon.com/powershell/latest/reference/items/New-EC2Snapshot.html](https://docs.aws.amazon.com/powershell/latest/reference/items/New-EC2Snapshot.html) cmdlet。使用上一步中的卷 ID。

   ```
   New-EC2Snapshot `
       -VolumeId vol-01234567890abcdef `
       -Description "my snapshot"
   ```

   下面是示例输出。

   ```
   AvailabilityZone          : 
   Description               : my snapshot
   Encrypted                 : False
   FullSnapshotSizeInBytes   : 0
   KmsKeyId                  : 
   OwnerId                   : 123456789012
   RestoreExpiryTime         : 
   SnapshotId                : snap-0abcdef1234567890
   SseType                   : 
   StartTime                 : 4/25/2025 6:08:59 PM
   State                     : pending
   StateMessage              : 
   VolumeId                  : vol-01234567890abcdef
   VolumeSize                : 30
   ```

1. 等到快照状态为 `completed` 后，继续执行下一步。要获取快照状态，请将 [https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Snapshot.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Snapshot.html) cmdlet 与上一步中的快照 ID 结合使用。

   ```
   (Get-EC2Snapshot `
       -SnapshotId snap-0abcdef1234567890).State.Value
   ```

   下面是示例输出。

   ```
   completed
   ```

1. 要创建新的 AMI，请使用 [https://docs.aws.amazon.com/powershell/latest/reference/items/Register-EC2Image.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Register-EC2Image.html) cmdlet。使用 **New-EC2Snapshot** 输出中 `SnapshotId` 的值。
   + 要将启动模式设置为 UEFI，请添加 `-BootMode` 参数，并指定值 `uefi`。

     ```
     $block = @{SnapshotId=snap-0abcdef1234567890}
     Register-EC2Image ` 
        -Description "my image" `
        -Name "my-image" `
        -BlockDeviceMapping @{DeviceName="/dev/xvda";Ebs=$block} `
        -RootDeviceName /dev/xvda `
        -EnaSupport $true `
        -BootMode uefi
     ```
   + 要将启动模式设置为 `uefi-preferred`，请将 `-BootMode` 的值设置为 `uefi-preferred`

     ```
     $block = @{SnapshotId=snap-0abcdef1234567890}
     Register-EC2Image ` 
        -Description "my image" `
        -Name "my-image" `
        -BlockDeviceMapping @{DeviceName="/dev/xvda";Ebs=$block} `
        -RootDeviceName /dev/xvda `
        -EnaSupport $true `
        -BootMode uefi-preferred
     ```

1. （可选）要验证新创建的 AMI 是否具有您指定的启动模式，请使用 [https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Image.html](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Image.html) cmdlet。

   ```
   (Get-EC2Image `
       -ImageId ami-1234567890abcdef0).BootMode.Value
   ```

   下面是示例输出。

   ```
   uefi
   ```

------

# Amazon EC2 实例的 UEFI 变量
<a name="uefi-variables"></a>

当您启动实例且其启动模式设置为 UEFI 时，将为变量创建键值存储。UEFI 和实例操作系统可以使用该键值存储来存储 UEFI 变量。

启动加载程序和操作系统使用 UEFI 变量来配置早期系统启动。它们允许操作系统管理启动过程的某些设置（例如启动顺序）或管理 UEFI 安全启动的密钥。

**警告**  
可以连接到实例的任何人（以及可能在实例上运行的任何软件），或者有权在实例上使用 [GetInstanceUefiData](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_GetInstanceUefiData.html) API 的任何人都可以读取变量。您绝不应将敏感数据（例如密码或个人身份信息）存储在 UEFI 变量存储中。

**UEFI 变量持久性**
+ 对于在 2022 年 5 月 10 日或之前启动的实例，UEFI 变量会在重启或停止时擦除。
+ 对于在 2022 年 5 月 11 日或之后启动的实例，标记为非易失性的 UEFI 变量将在重启和停止/启动时保留。
+ 裸机实例不会在实例停止/启动操作中保留 UEFI 非易失性变量。

# 适用于 Amazon EC2 实例的 UEFI 安全启动
<a name="uefi-secure-boot"></a>

UEFI 安全启动构建在 Amazon EC2 长期以来的安全启动过程之上，并提供了额外的深度防御功能，可以帮助客户保护软件免受重新引导过程中持续存在的威胁。它确保实例只启动使用了加密密钥签名的软件。密钥存储在 [UEFI 非易失性变量存储](uefi-variables.md)的密钥数据库中。UEFI 安全启动可防止未经授权地修改实例启动流程。

**Topics**
+ [如何将 UEFI 安全启动与 Amazon EC2 实例配合使用](how-uefi-secure-boot-works.md)
+ [Amazon EC2 上 UEFI 安全启动的要求](launch-instance-with-uefi-sb.md)
+ [验证 Amazon EC2 实例是否启用了 UEFI 安全启动](verify-uefi-secure-boot.md)
+ [使用自定义 UEFI 安全启动密钥创建 Linux AMI](create-ami-with-uefi-secure-boot.md)
+ [为 UEFI 安全启动创建 AWS 二进制 blob](aws-binary-blob-creation.md)

# 如何将 UEFI 安全启动与 Amazon EC2 实例配合使用
<a name="how-uefi-secure-boot-works"></a>

UEFI 安全启动是 UEFI 中指定的一项功能，它提供了有关启动链状态的验证。它旨在确保固件自初始化后只执行经过加密验证的 UEFI 二进制文件。这些二进制文件包括 UEFI 驱动程序和主启动加载程序以及链加载组件。

UEFI 安全启动指定了四个密钥数据库，这些数据库在信任链中使用。数据库存储在 UEFI 变量存储中。

信任链如下所示：

**平台密钥（PK）数据库**  
PK 数据库是信任根。它包含一个公有 PK 密钥，该密钥在信任链中用于更新密钥交换密钥（KEK）数据库。  
要更改 PK 数据库，必须拥有私有 PK 密钥才能签署更新请求。这包括通过写入空 PK 密钥来删除 PK 数据库。

**密钥交换密钥（KEK）数据库**  
KEK 数据库是信任链中用于更新签名（db）和拒绝列表（dbx）数据库的公有 KEK 密钥的列表。  
要更改公有 KEK 数据库，必须拥有私有 PK 密钥才能签署更新请求。

**签名（db）数据库**  
db 数据库是信任链中用于验证所有 UEFI 启动二进制文件的公有密钥和哈希值的列表。  
要更改 db 数据库，必须拥有私有 PK 密钥或私有 KEK 密钥中的任何一个才能签署更新请求。

**签名拒绝列表（dbx）数据库**  
dbx 数据库是不受信任的公有密钥和二进制哈希的列表，在信任链中用作吊销文件。  
dbx 数据库始终优先于所有其他密钥数据库。  
要更改 dbx 数据库，必须拥有私有 PK 密钥或私有 KEK 密钥中的任何一个才能签署更新请求。  
UEFI 论坛在 [https://uefi.org/revocationlistfile](https://uefi.org/revocationlistfile) 为许多已知不良的二进制文件和证书维护了公开可用的 dbx。

**重要**  
UEFI 安全启动在任何 UEFI 二进制文件上强制执行签名验证。要允许在 UEFI 安全启动中执行 UEFI 二进制文件，请使用上述任何私有 db 密钥对其进行签名。

默认情况下，UEFI 安全启动处于禁用状态，且系统处于 `SetupMode`。当系统处于 `SetupMode` 时，所有密钥变量都可以在没有加密签名的情况下进行更新。设置 PK 后，启用 UEFI 安全启动并退出 SetupMode。

# Amazon EC2 上 UEFI 安全启动的要求
<a name="launch-instance-with-uefi-sb"></a>

当您使用支持的 AMI 和支持的实例类型[启动 Amazon EC2 实例](LaunchingAndUsingInstances.md)时，该实例将根据其 UEFI 安全启动数据库自动验证 UEFI 启动二进制文件。无需其他配置。您还可以在启动后在实例上配置 UEFI 安全启动。

**注意**  
UEFI 安全启动可以保护您的实例及其操作系统免受启动流程修改的影响。如果从启用了 UEFI 安全引导的源 AMI 创建新的 AMI，并在复制过程中修改了某些参数，如更改了 AMI 中的 `UefiData`，则可以禁用 UEFI 安全引导。

**Topics**
+ [支持的 AMI](#uefi-amis)
+ [支持的实例类型](#uefi-instance)

## 支持的 AMI
<a name="uefi-amis"></a>

**Linux AMI**  
要启动 Linux 实例，Linux AMI 必须启用 UEFI 安全引导。

从 AL2023 2023.1 版本开始，Amazon Linux 支持 UEFI 安全启动。但是，默认 AMI 中不会启用 UEFI 安全启动。有关更多信息，请参阅《AL2023 User Guide》**中的 [UEFI Secure Boot](https://docs.aws.amazon.com/linux/al2023/ug/uefi-secure-boot.html)。旧版本的 Amazon Linux AMI 不会为 UEFI 安全启动启用。要使用受支持的 AMI，您必须在自己的 Linux AMI 上执行多个配置步骤。有关更多信息，请参阅 [使用自定义 UEFI 安全启动密钥创建 Linux AMI](create-ami-with-uefi-secure-boot.md)。

**Windows AMI**  
要启动 Windows 实例，Windows AMI 必须启用 UEFI 安全引导。要查找使用 Microsoft 密钥为 UEFI 安全启动预先配置的 AWS Windows AMI，请参阅《AWS Windows AMIs Reference》**中的 [Find Windows Server AMIs configured with NitroTPM and UEFI Secure Boot](https://docs.aws.amazon.com/ec2/latest/windows-ami-reference/ami-windows-tpm.html#ami-windows-tpm-find)。

目前，我们不支持使用 [import-image](https://docs.aws.amazon.com/cli/latest/reference/ec2/import-image.html) 命令导入包含 UEFI 安全启动的 Windows。

## 支持的实例类型
<a name="uefi-instance"></a>

所有支持 UEFI 的虚拟化实例类型也支持 UEFI 安全启动。有关支持 UEFI 安全引导的实例类型，请参阅 [UEFI 启动模式的要求](launch-instance-boot-mode.md)。

**注意**  
裸机实例类型不支持 UEFI 安全启动。

# 验证 Amazon EC2 实例是否启用了 UEFI 安全启动
<a name="verify-uefi-secure-boot"></a>

您可以使用以下过程确定 Amazon EC2 是否启用了 UEFI 安全启动。

## Linux 实例
<a name="verify-uefi-secure-boot-linux"></a>

您可以使用 `mokutil` 实用程序验证 Linux 实例是否启用了 UEFI 安全启动。如果实例上未安装 `mokutil`，则必须进行安装。有关 Amazon Linux 2 的安装说明，请参阅 [Find and install software packages on an Amazon Linux 2 instance](https://docs.aws.amazon.com/linux/al2/ug/find-install-software.html)。有关其他 Linux 发行版，请参阅特定于该版本的文档。

**验证 Linux 实例是否启用了 UEFI 安全启动**  
连接到您的实例并在终端窗口中作为 `root` 运行以下命令。

```
mokutil --sb-state 
```

下面是示例输出。
+ 如果启用了 UEFI 安全启动，则输出包含 `SecureBoot enabled`。
+ 如果未启用 UEFI 安全启动，则输出将包含 `SecureBoot disabled` 或 `Failed to read SecureBoot`。

## Windows 实例
<a name="verify-uefi-secure-boot-windows"></a>

**验证 Windows 实例是否启用了 UEFI 安全启动**

1. 连接到您的实例。

1. 打开 msinfo32 工具。

1. 检查 **Secure Boot State**（安全启动状态）字段。如果启用了 UEFI 安全启动，则该值为**支持**，如下图所示。  
![\[系统信息中的安全启动状态。\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/images/secure-boot-state-win.png)

您还可以使用 Windows PowerShell Cmdlet `Confirm-SecureBootUEFI` 来检查安全启动状态。有关 cmdlet 的更多信息，请参阅 Microsoft 文档中的 [Confirm-SecureBootUEFI](https://learn.microsoft.com/en-us/powershell/module/secureboot/confirm-securebootuefi)。

# 使用自定义 UEFI 安全启动密钥创建 Linux AMI
<a name="create-ami-with-uefi-secure-boot"></a>

这些说明向您展示如何使用 UEFI 安全启动和定制私有密钥创建 Linux AMI。从 AL2023 2023.1 版本开始，Amazon Linux 支持 UEFI 安全启动。有关更多信息，请参阅《*Amazon Linux 2023 用户指南*》中的 [UEFI Secure Boot on AL2023](https://docs.aws.amazon.com/linux/al2023/ug/uefi-secure-boot.html)。

**重要**  
以下过程**仅供高级用户使用**。您必须对 SSL 和 Linux 发行版启动流程有足够的了解才能使用这些步骤。

**先决条件**
+ 将使用以下工具：
  + OpenSSL – [https://www.openssl.org/](https://www.openssl.org/)
  + efivar – [https://github.com/rhboot/efivar](https://github.com/rhboot/efivar)
  + efitools – [https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git/](https://git.kernel.org/pub/scm/linux/kernel/git/jejb/efitools.git/)
  + [get-instance-uefi-data](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-uefi-data.html) 命令
+ 您的 Linux 实例必须使用支持 UEFI 启动模式的 Linux AMI 启动，并且存在非易失性数据。

在 `SetupMode` 中创建了没有 UEFI 安全启动密钥的新创建的实例，从而使您能够注册自己的密钥。有些 AMI 预先配置了 UEFI 安全启动，您无法更改现有密钥。如果要更改密钥，您必须基于原始 AMI 创建新 AMI。

有两种方法可以在变量存储中传播密钥，这些方法在后面的选项 A 和选项 B 中进行说明。选项 A 描述了如何在实例内执行此操作，以模仿真实硬件的流程。选项 B 描述了如何创建二进制 Blob，然后在创建 AMI 时将其作为 base64 编码文件传递。对于这两种选项，您必须首先创建三个密钥对，它们将用于信任链。

**Topics**
+ [任务 1：创建密钥对](#uefi-secure-boot-create-three-key-pairs)
+ [任务 2 - 选项 A：从实例内向变量存储添加密钥](#uefi-secure-boot-optionA)
+ [任务 2 - 选项 B：创建包含预填充变量存储的二进制 blob](#uefi-secure-boot-optionB)

## 任务 1：创建密钥对
<a name="uefi-secure-boot-create-three-key-pairs"></a>

UEFI 安全启动基于在信任链中使用的以下三个密钥数据库：平台密钥（PK）、密钥交换密钥（KEK）和签名数据库（db）。¹

在实例上创建每个密钥。要以对 UEFI 安全启动标准有效的格式准备公钥，请为每个密钥创建一个证书。`DER` 定义 SSL 格式（格式的二进制编码）。然后，您将每个证书转换为 UEFI 签名列表，这是 UEFI 安全启动所理解的二进制格式。最后，使用相关密钥签署每个证书。

**Topics**
+ [准备创建密钥对](#uefisb-prepare-to-create-key-pairs)
+ [密钥对 1：创建平台密钥（PK）](#uefisb-create-key-pair-1)
+ [密钥对 2：创建密钥交换密钥（KEK）](#uefisb-create-key-pair-2)
+ [密钥对 3：创建签名数据库（db）](#uefisb-create-key-pair-3)
+ [用私有密钥签署启动映像（内核）](#uefi-secure-boot-sign-kernel)

### 准备创建密钥对
<a name="uefisb-prepare-to-create-key-pairs"></a>

在创建密钥对之前，请创建用于密钥生成的全局唯一标识符（GUID）。

1. [连接到实例。](connect.md)

1. 在 Shell 提示符中运行以下命令。

   ```
   uuidgen --random > GUID.txt
   ```

### 密钥对 1：创建平台密钥（PK）
<a name="uefisb-create-key-pair-1"></a>

PK 是 UEFI 安全启动实例的信任根。私有 PK 用于更新 KEK，这反过来又可以用来将授权密钥添加到签名数据库（db）。

X.509 标准用于创建密钥对。有关标准的信息，请参阅 *Wikipedia* 上的 [X.509](https://en.wikipedia.org/wiki/X.509)。

**要创建 PK**

1. 创建密钥。您必须将变量命名为 `PK`。

   ```
   openssl req -newkey rsa:4096 -nodes -keyout PK.key -new -x509 -sha256 -days 3650 -subj "/CN=Platform key/" -out PK.crt
   ```

   指定了以下参数：
   + `-keyout PK.key` – 私有密钥文件。
   + `-days 3650` – 证书的有效天数。
   + `-out PK.crt` – 用于创建 UEFI 变量的证书。
   + `CN=Platform key` – 密钥的公用名（CN）。您可以输入您自己企业的名称而不是*平台密钥*。

1. 创建证书。

   ```
   openssl x509 -outform DER -in PK.crt -out PK.cer
   ```

1. 将证书转换为 UEFI 签名列表。

   ```
   cert-to-efi-sig-list -g "$(< GUID.txt)" PK.crt PK.esl
   ```

1. 使用私有 PK（自签名）签署 UEFI 签名列表。

   ```
   sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt PK PK.esl PK.auth
   ```

### 密钥对 2：创建密钥交换密钥（KEK）
<a name="uefisb-create-key-pair-2"></a>

私有 KEK 用于向 db 添加密钥，该数据库是要在系统上启动的授权签名列表。

**要创建 KEK**

1. 创建密钥。

   ```
   openssl req -newkey rsa:4096 -nodes -keyout KEK.key -new -x509 -sha256 -days 3650 -subj "/CN=Key Exchange Key/" -out KEK.crt
   ```

1. 创建证书。

   ```
   openssl x509 -outform DER -in KEK.crt -out KEK.cer
   ```

1. 将证书转换为 UEFI 签名列表。

   ```
   cert-to-efi-sig-list -g "$(< GUID.txt)" KEK.crt KEK.esl
   ```

1. 使用私有 PK 签署签名列表。

   ```
   sign-efi-sig-list -g "$(< GUID.txt)" -k PK.key -c PK.crt KEK KEK.esl KEK.auth
   ```

### 密钥对 3：创建签名数据库（db）
<a name="uefisb-create-key-pair-3"></a>

db 列表包含授权在系统上启动的授权密钥。要修改列表，需要私有 KEK。启动映像将使用此步骤中创建的私有密钥签名。

**要创建 db**

1. 创建密钥。

   ```
   openssl req -newkey rsa:4096 -nodes -keyout db.key -new -x509 -sha256 -days 3650 -subj "/CN=Signature Database key/" -out db.crt
   ```

1. 创建证书。

   ```
   openssl x509 -outform DER -in db.crt -out db.cer
   ```

1. 将证书转换为 UEFI 签名列表。

   ```
   cert-to-efi-sig-list -g "$(< GUID.txt)" db.crt db.esl
   ```

1. 用私有 KEK 签署签名列表。

   ```
   sign-efi-sig-list -g "$(< GUID.txt)" -k KEK.key -c KEK.crt db db.esl db.auth
   ```

### 用私有密钥签署启动映像（内核）
<a name="uefi-secure-boot-sign-kernel"></a>

对于 Ubuntu 22.04，以下映像需要签名。

```
/boot/efi/EFI/ubuntu/shimx64.efi
/boot/efi/EFI/ubuntu/mmx64.efi
/boot/efi/EFI/ubuntu/grubx64.efi
/boot/vmlinuz
```

**要签署映像**  
使用以下语法签署映像。

```
sbsign --key db.key --cert db.crt --output /boot/vmlinuz /boot/vmlinuz
```

**注意**  
您必须签署所有新内核。*`/boot/vmlinuz`* 通常会将符号链接到上次安装的内核。

请参阅您的发行版的文档以了解启动链和所需映像。

¹ 感谢 ArchWiki 社区所做的所有工作。创建 PK、创建 KEK、创建数据库和签署映像的命令来自[创建密钥](https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#Creating_keys)，由 ArchWiki 维护团队和/或 ArchWiki 贡献者撰写。

## 任务 2 - 选项 A：从实例内向变量存储添加密钥
<a name="uefi-secure-boot-optionA"></a>

创建了[三个密钥对](#uefi-secure-boot-create-three-key-pairs)后，您可以通过完成以下步骤连接到实例并从实例内将密钥添加到变量存储中。或者，完成[任务 2 - 选项 B：创建包含预填充变量存储的二进制 blob](#uefi-secure-boot-optionB)中的步骤。

**Topics**
+ [步骤 1：启动将支持 UEFI 安全启动的实例](#step1-launch-uefi-sb)
+ [步骤 2：配置实例以支持 UEFI 安全启动](#step2-launch-uefi-sb)
+ [步骤 3：从实例创建 AMI](#step3-launch-uefi-sb)

### 步骤 1：启动将支持 UEFI 安全启动的实例
<a name="step1-launch-uefi-sb"></a>

当您使用以下先决条件[启动实例](LaunchingAndUsingInstances.md)时，该实例将准备好配置为支持 UEFI 安全启动。您只能在启动时在实例上启用对 UEFI 安全启动的支持；无法在以后启用它。

**先决条件**
+ **AMI** – Linux AMI 必须支持 UEFI 启动模式。要验证 AMI 是否支持 UEFI 启动模式，AMI 启动模式参数必须为 **uefi**。有关更多信息，请参阅 [确定 Amazon EC2 AMI 的启动模式参数](ami-boot-mode.md)。

  请注意，AWS 仅提供配置为支持基于 Graviton 实例类型的 UEFI 的 Linux AMI。AWS 当前不提供支持 UEFI 启动模式的 x86\$164 Linux AMI。您可以配置自己的 AMI 以支持所有架构的 UEFI 启动模式。若要配置自己的 AMI 以支持 UEFI 启动模式，您必须在自己的 AMI 上执行多个配置步骤。有关更多信息，请参阅 [设置 Amazon EC2 AMI 的启动模式](set-ami-boot-mode.md)。
+ **实例类型** – 许多支持 UEFI 的虚拟化实例类型也支持 UEFI 安全启动。裸机实例类型不支持 UEFI 安全启动。有关支持 UEFI 安全引导的实例类型，请参阅 [UEFI 启动模式的要求](launch-instance-boot-mode.md)。
+ 在 UEFI 安全启动发布后启动您的实例。只有在 2022 年 5 月 10 日（UEFI 安全启动发布时）之后启动的实例才能支持 UEFI 安全启动。

启动实例后，您可以通过检查是否存在 UEFI 数据来验证它是否已准备好配置为支持 UEFI 安全启动（换句话说，您可以继续[步骤 2](#step2-launch-uefi-sb)）。UEFI 数据的存在表明非易失性数据是持久的。

**验证您的实例是否已为步骤 2 做好准备**  
使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-uefi-data.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-uefi-data.html) 命令并指定实例 ID。

```
aws ec2 get-instance-uefi-data --instance-id i-1234567890abcdef0
```

如果输出中存在 UEFI 数据，则实例已准备好进入步骤 2。如果输出为空，则无法将实例配置为支持 UEFI 安全启动。如果您的实例在 UEFI 安全启动支持可用之前启动，则可能会发生这种情况。启动新实例，然后重试。

### 步骤 2：配置实例以支持 UEFI 安全启动
<a name="step2-launch-uefi-sb"></a>

#### 在实例上的 UEFI 变量存储中注册密钥对
<a name="step2a-launch-uefi-sb"></a>

**警告**  
您必须在注册密钥*之后*签署启动映像，否则您将无法启动实例。

创建签名的 UEFI 签名列表后（`PK`、`KEK` 和 `db`），必须将它们注册到 UEFI 固件中。

只有在以下情况下才能写入 `PK` 变量：
+ 尚未注册 PK，当 `SetupMode` 变量为 `1` 时即表明这一点。使用以下命令检查此内容。输出为 `1` 或 `0`。

  ```
  efivar -d -n 8be4df61-93ca-11d2-aa0d-00e098032b8c-SetupMode 
  ```
+ 新 PK 由现有 PK 的私有密钥签名。

**在 UEFI 变量存储中注册密钥**  
以下命令必须在实例上运行。

如果启用了 SetupMode（值为 `1`），您可以通过在实例上运行以下命令注册密钥：

```
[ec2-user ~]$ efi-updatevar -f db.auth db
```

```
[ec2-user ~]$ efi-updatevar -f KEK.auth KEK
```

```
[ec2-user ~]$ efi-updatevar -f PK.auth PK
```

**验证 UEFI 安全启动是否已启用**  
要验证 UEFI 安全启动是否已启用，请遵照 [验证 Amazon EC2 实例是否启用了 UEFI 安全启动](verify-uefi-secure-boot.md) 中的步骤。

现在，您可以使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-uefi-data.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-uefi-data.html) CLI 命令导出 UEFI 变量存储，或者继续执行下一步并签署启动映像，以重新启动到启用了 UEFI 安全启动的实例中。

### 步骤 3：从实例创建 AMI
<a name="step3-launch-uefi-sb"></a>

要从实例创建 AMI，您可以使用控制台或 `CreateImage` API、CLI 或开发工具包。有关控制台说明，请参阅 [创建 Amazon EBS-backed AMI](creating-an-ami-ebs.md)。有关 API 说明，请参阅 [CreateImage](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateImage.html)。

**注意**  
`CreateImage` API 会自动将实例的 UEFI 变量存储复制到 AMI。控制台会使用 `CreateImage` API。使用此 AMI 启动实例后，实例将具有相同的 UEFI 变量存储。

## 任务 2 - 选项 B：创建包含预填充变量存储的二进制 blob
<a name="uefi-secure-boot-optionB"></a>

创建了[三个密钥对](#uefi-secure-boot-create-three-key-pairs)后，您可以创建一个二进制 blob，其中包含含有 UEFI 安全启动密钥的预填充变量存储。或者，完成[任务 2 - 选项 A：从实例内向变量存储添加密钥](#uefi-secure-boot-optionA)中的步骤。

**警告**  
您必须先签署您的启动映像，*然后*才能注册密钥，否则您将无法启动实例。

**Topics**
+ [步骤 1：创建新的变量存储或更新现有变量存储](#uefi-secure-boot-create-or-update-variable)
+ [步骤 2：在 AMI 创建时上传二进制 blob](#uefi-secure-boot-upload-binary-blob-on-ami-creation)

### 步骤 1：创建新的变量存储或更新现有变量存储
<a name="uefi-secure-boot-create-or-update-variable"></a>

您可以使用 python-uefivars 工具*离线*创建变量存储，而不需要正在运行的实例。该工具可以从您的密钥中创建一个新的变量存储。该脚本目前支持 EDK2 格式、AWS 格式，以及使用更高级别的工具更容易编辑的 JSON 表示法。

**在没有运行实例的情况下离线创建变量存储**

1. 通过以下链接下载该工具。

   ```
   https://github.com/awslabs/python-uefivars
   ```

1. 通过运行以下命令从密钥创建新的变量存储。这将在 *your\$1binary\$1blob*.bin 中创建 base64 编码的二进制 blob。该工具还通过 `-I` 参数支持更新二进制 blob。

   ```
   ./uefivars.py -i none -o aws -O your_binary_blob.bin -P PK.esl -K KEK.esl --db db.esl --dbx dbx.esl
   ```

### 步骤 2：在 AMI 创建时上传二进制 blob
<a name="uefi-secure-boot-upload-binary-blob-on-ami-creation"></a>

使用 [https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html](https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html) 传递 UEFI 变量存储数据。对于 `--uefi-data` 参数，指定您的二进制 blob，对于 `--boot-mode` 参数，请指定 `uefi`。

```
aws ec2 register-image \
    --name uefi_sb_tpm_register_image_test \
    --uefi-data $(cat your_binary_blob.bin) \
    --block-device-mappings "DeviceName=/dev/sda1,Ebs= {SnapshotId=snap-0123456789example,DeleteOnTermination=true}" \
    --architecture x86_64 \
    --root-device-name /dev/sda1 \
    --virtualization-type hvm \
    --ena-support \
    --boot-mode uefi
```

# 为 UEFI 安全启动创建 AWS 二进制 blob
<a name="aws-binary-blob-creation"></a>

您可以使用以下步骤在 AMI 创建期间自定义 UEFI 安全启动变量。这些步骤中使用的 KEK 截止到 2021 年 9 月。如果 Microsoft 更新 KEK，您必须使用最新的 KEK。

**要创建 AWS 二进制 blob**

1. 创建一个空的 PK 签名列表。

   ```
   touch empty_key.crt
   cert-to-efi-sig-list empty_key.crt PK.esl
   ```

1. 下载 KEK 证书。

   ```
   https://go.microsoft.com/fwlink/?LinkId=321185
   ```

1. 将 KEK 证书包装在 UEFI 签名列表中（`siglist`）。

   ```
   sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_KEK.esl MicCorKEKCA2011_2011-06-24.crt 
   ```

1. 下载 Microsoft 的 db 证书。

   ```
   https://www.microsoft.com/pkiops/certs/MicWinProPCA2011_2011-10-19.crt
   https://www.microsoft.com/pkiops/certs/MicCorUEFCA2011_2011-06-27.crt
   ```

1. 生成 db 签名列表。

   ```
   sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_Win_db.esl MicWinProPCA2011_2011-10-19.crt
   sbsiglist --owner 77fa9abd-0359-4d32-bd60-28f4e78f784b --type x509 --output MS_UEFI_db.esl MicCorUEFCA2011_2011-06-27.crt
   cat MS_Win_db.esl MS_UEFI_db.esl > MS_db.esl
   ```

1. Unified Extensible Firmware Interface Forum 不再提供 DBX 文件。这些文件现在由 Microsoft 在 GitHub 上提供。请从 Microsoft 安全启动更新存储库下载最新的 DBX 更新，网址为 [https://github.com/microsoft/secureboot\$1objects](https://github.com/microsoft/secureboot_objects)。

1. 解压已签名的更新二进制文件。

   使用下面的脚本内容创建 `SplitDbxContent.ps1`。或者，也可以使用 `Install-Script -Name SplitDbxContent` 从 [PowerShell Gallery](https://www.powershellgallery.com/packages/SplitDbxContent/1.0) 安装脚本。

   ```
   <#PSScriptInfo
    
   .VERSION 1.0
    
   .GUID ec45a3fc-5e87-4d90-b55e-bdea083f732d
    
   .AUTHOR Microsoft Secure Boot Team
    
   .COMPANYNAME Microsoft
    
   .COPYRIGHT Microsoft
    
   .TAGS Windows Security
    
   .LICENSEURI
    
   .PROJECTURI
    
   .ICONURI
    
   .EXTERNALMODULEDEPENDENCIES
    
   .REQUIREDSCRIPTS
    
   .EXTERNALSCRIPTDEPENDENCIES
    
   .RELEASENOTES
   Version 1.0: Original published version.
    
   #>
   
   <#
   .DESCRIPTION
    Splits a DBX update package into the new DBX variable contents and the signature authorizing the change.
    To apply an update using the output files of this script, try:
    Set-SecureBootUefi -Name dbx -ContentFilePath .\content.bin -SignedFilePath .\signature.p7 -Time 2010-03-06T19:17:21Z -AppendWrite'
   .EXAMPLE
   .\SplitDbxAuthInfo.ps1 DbxUpdate_x64.bin
   #>
   
   
   # Get file from script input
   $file  = Get-Content -Encoding Byte $args[0]
   
   # Identify file signature
   $chop = $file[40..($file.Length - 1)]
   if (($chop[0] -ne 0x30) -or ($chop[1] -ne 0x82 )) {
       Write-Error "Cannot find signature"
       exit 1
   }
   
   # Signature is known to be ASN size plus header of 4 bytes
   $sig_length = ($chop[2] * 256) + $chop[3] + 4
   $sig = $chop[0..($sig_length - 1)]
   
   if ($sig_length -gt ($file.Length + 40)) {
       Write-Error "Signature longer than file size!"
       exit 1
   }
   
   # Content is everything else
   $content = $file[0..39] + $chop[$sig_length..($chop.Length - 1)]
   
   # Write signature and content to files
   Set-Content -Encoding Byte signature.p7 $sig
   Set-Content -Encoding Byte content.bin $content
   ```

   使用该脚本解压缩已签名的 DBX 文件。

   ```
   PS C:\Windows\system32> SplitDbxContent.ps1 .\dbx.bin
   ```

   这会生成两个文件：`signature.p7` 和 `content.bin`。在下一步中使用 `content.bin`。

1. 使用 `uefivars.py` 脚本构建 UEFI 变量存储。

   ```
   ./uefivars.py -i none -o aws -O uefiblob-microsoft-keys-empty-pk.bin -P ~/PK.esl -K ~/MS_Win_KEK.esl --db ~/MS_db.esl  --dbx ~/content.bin 
   ```

1. 检查二进制 blob 和 UEFI 变量存储。

   ```
   ./uefivars.py -i aws -I uefiblob-microsoft-keys-empty-pk.bin -o json | less
   ```

1. 您可以通过再次将 blob 传递给同一个工具来更新它。

   ```
   ./uefivars.py -i aws -I uefiblob-microsoft-keys-empty-pk.bin -o aws -O uefiblob-microsoft-keys-empty-pk.bin -P ~/PK.esl -K ~/MS_Win_KEK.esl --db ~/MS_db.esl  --dbx ~/content.bin
   ```

   预期输出

   ```
   Replacing PK
   Replacing KEK
   Replacing db
   Replacing dbx
   ```