在 $300 的手机上启动 Windows 10 ARM64

imbushuo

Please mind the gap

86人赞了该文章

这是上一篇文章的续集。总的来说,差异不是特别大,但是也有一些细节上的不同。


这是这只 $300 的手机。价格刚刚从美亚截图的众所周知,Windows Phone 8 和 Windows 10 Mobile 没有发布过正式的 AArch64 版本。所以即使在 Lumia 950, 950XL, HP Elite x3 之类的设备上,他们也是以 AArch32 模式运行的(向下兼容)。

从具体实现细节说,Snapdragon 808 和 810 以 AArch32 模式启动第一个核心并初始化(但是 TZ 是 AArch64 的),根据需求通过 Secure Monitor Call 来切换 PL1/EL1 的 bitness。Snapdragon 820 以 AArch64 模式启动第一个核心,根据需求在启动 Windows Phone UEFI 时进入 AArch32 的 EL1。

所以在给 Lumia 移植了 LK 之后,我们就有相对充足的 EL1 控制权(在高通设备上 EL2 和 EL3 是不受我们控制的)。因此我们也可以载入我们自己的 TianoCore Payload 到内存,然后通过 SMC 切换 bitness 并执行。具体怎么从 Boot Manager 启动 LK,看这里。

UEFI 相关

首先在 ARM 上 UEFI 的初始化工作比 x86 通常要小很多,因为 UEFI 一般被作为一个 Secondary Bootloader 被载入,载入的时候,DDR 训练已经完成了,内存可以直接拿来用了。而且这些嵌入式设备有很多硬编码的参数。

剩下的内容并不是特别麻烦,EFIDroid 项目提供了很多不错的参考实现,直接拿来用就好。不过我重写了内存初始化(其实是 MMU 和 HOB)部分来适应 Windows 的启动要求。

USB 还没来得及做,但是都是 Synposys 的 USB IP,可以参考 RaspberryPiPkg 里的相关内容。估计 Clock 部分要和 EFIDroid 的驱动做集成。

一个正在进行中的 Lumia 950 XL 参考 UEFI 实现看这里。目前代码还很乱。

UART

很不幸 Lumia 950XL 没有外置的(唯一一个接了蓝牙)。所以我们用屏幕当串口来诊断一些问题。我把这个选项做成了一个 PCD,在我的实现发布里默认没开。其实其他 Lumia 非 x50 代的都有能用的 UART 测试点,使用的是 1.8V UART(高通常见)。

多核启动

可以先看一下老狼的这篇文章,对多核启动有一个了解:兄弟阋墙,CPU内核们是如何争当老大的?

在 ARM 平台上,目前通行的几种多核启动办法如下:

第二种办法在核心运行的 Hold 伪代码如下:

Hold:
   等一个中断过来,没有来就睡觉
   判断一下是不是我要起床了(检查核心 ID),是的话跳转到指定内存地址并继续执行
   不是我起床,回到 Hold 重复

第三种办法直接向 EL2/3 发送 Hypervisor Call 或者 Secure Monitor Call。虽然 Lumia 950 XL 所用的 Snapdragon 810 没有标注 PSCI 支持,但是实际上支持了一部分 PSCI 内容。PSCI CPU_ON 是没问题的,但是其他电源操作还是需要通过 SPMI 给 PMIC 发指令。所以我们在 ACPI 里标注了 PSCI 支持(并要求 Hypervisor Call),但是 UEFI 库里的其他电源操作还是通过 PMIC 完成。

不过看上去 HVC PSCI 没法让 Linux 带起来。Linux 只能单核启动,尚未调查具体原因。

完成了这些内容后,Windows 就能启动了。不过把各种外设带起来,还需要挺长的时间。后面是几张图。




还有几张号外。


发布于2018-05-04 18:16
编辑于2018-05-08 14:15

文章被以下专栏收录