So you want to run Windows 10 on a calculator? okay



HP Prime G2 under Windows 10 IoT



One could only dream of starting Windows on a standard calculator before the advent of the HP Prime G2. A calculator on such a powerful hardware has never entered the market. And more importantly, HP has chosen the ARMv7-A processor! This article discusses how to install UEFI and ACPI on a device.





SoC specifications on the HP Prime G2. SoC NXP i.MX 6ULL ​​(Ultra Lite) has a single-core Cortex A7 processor



Previous work



My friend Wenxin Zhang (Zephray) did the fundamental work of reverse engineering the GPIO and the technical characteristics of the calculator. In addition, he managed to port working U-Boot and Linux to the calculator.



According to TI-Planet , the calculator provides a large number of test pins, including SD / MMC, JTAG and UART.



Sarah (winocm) studied the possibility of running Windows RT on the Qemu platform. By 2019, something has changed, but the article has not lost its value.



Microsoft has entered into an NXP agreement to provide support for Windows 10 IoT on iMX SoC chips. Thus, technically, Windows 10 IoT should work on this calculator (as well as Windows on ARM).



Refine Windows system requirements



System requirements for running the Windows 10 family of OSs are listed on the Microsoft Docs website . Even the most minimal requirements are more than Linux: the system needs an x86 / x64 / ARMv7 / AArch64 processor, at least 256 MB of memory and 2 GB of disk space. Requires functional UEFI firmware, complete ACPI and SMBIOS tables.



In our case, there is not enough space on the device (and Windows also does not support Raw SLC NAND), but you can connect the boot device via USB to the calculator.



Sara lists the architectural requirements for ARMv7 to run Windows. Over the years, the requirements have changed a bit, here's what they look like at the moment:



  System processor: ARMv7-A compatible processor with VFPv3 + VFP HalfPrec, VFPv4 is also suitable
 Memory: at least 256 MB RAM (probably less)
 Peripherals:
     - System timer (either by architecture or by vendor)
     - ARM Generic Interrupt Controller (GIC) or Broadcom Interrupt Controller on BCM2835 / 2836/2837, CPU and Distributor Interface.  If GIC is present and declared in the system, GICv2 and above are required.
     - framebuffer
     - Support for UART, or NS16550, BCM283x, or from the vendor (in the case of Qualcomm and NXP)
     - Firmware: UEFI 2.3 or higher 


Our calculator meets these stringent requirements. However, the default SoC runs at 396 MHz, which is less than the base level of 400 MHz / 1 GHz. 250 MB of system memory is also reported, while the minimum requirement for a system with a UI is 512 MB. But it is loading!





According to cpuinfo from WinDbg, SoC runs at 396 MHz



I think you can further reduce the requirements. If I remember correctly, Windows Server Nano has about 150 MB of memory to boot on amd64 systems.



UEFI and ACPI



I have written several times about UEFI implementations , so there is nothing new here. Basically, UEFI consists of a set of device drivers and TianoCore kernel components . ACPI tables are copied from the Windows IoT iMX Project Mu repository and trimmed.



UEFI boots from U-Boot . iMX by default does not allow access to unaligned memory, and this causes a lot of problems during the UEFI DXE and BDS stages, so you should enable it as soon as possible.



  mrc p15, 0, r0, c1, c0, 0
  bic r0, r0, # 2
  mcr p15, 0, r0, c1, c0, 0 


A compiler with hardware support for float speeds up the bootloader from about 30 to 4 seconds. On ARMv7 platforms, Windows claims support for VFPv3 +.



Screen initialization, as well as some I / O mux assignments, are done in U-Boot. Now U-Boot does not support the 24 / 32bpp Serial RGB LCD interface, so I added Serial RGB support through the implementation of the iMX framebuffer in the Linux kernel. The code is not in the wizard yet, but I will pass it there later.







LCD seems to work. The whole procedure:



  1. Launch uboot.

  2. Find a pin for the screen backlight.

  3. Find pin for SPI and LCD initialization sequence.

  4. Find the I2C pin and configure the PMIC via I2C for the correct voltage.




Serial RGB LCD Interface Demonstration in U-Boot



UEFI simply takes the framebuffer allocated by U-Boot and registers the Graphics Output Protocol. Unfortunately, the screen resolution does not meet the minimum requirements of the 80 * 25 console, so I changed the Console DXE components by adding a new 40 * 12 mode.





The EDK2 component claims that the screen resolution does not meet the minimum requirements of the 80 * 25 console



Before the hack of the console components, I did a little trick, fixing the resolution of 640 * 480 into the UEFI GOP protocol. The trick also helped get diagnostic information from the Windows Boot Manager, because the 320 * 240 resolution is not enough to display the error code. I periodically run block-transfer (BLT) from the framebuffer to the file system and save the BMP files to a USB drive.





Hack makes available 80 * 25 mode with some graphic artifacts



After connecting a new mode, image quality is greatly improved.





40 * 12 mode





40 * 12 mode



Here's what the Windows Boot Manager message looks like at a resolution of 320 * 240:







The first attempt fails at the UEFI boot services stage. The error code is not visible due to the small screen.





Block-transfer (BLT) from the framebuffer allows you to save the message to an image file and read it



Regarding USB support. Fortunately, USB in the iMX6 is fully compliant, and support is included in recent versions of Windows. Therefore, as soon as I configured the OTG controller in host mode and transferred the MMIO area to UEFI and Windows, it magically works without problems. But we did not find VBus on the OTG port (we assume that there is some kind of DC-DC circuit controlled by SoC or PMIC, but this is only an unverified hypothesis), therefore, for the correct operation, the port needs to be powered through some external source.



SMBIOS



Make sure that you correctly report the memory size and address areas in SMBIOS, or Windows will start to do incredibly strange things (tm).





Windows debugger cannot read memory due to incorrect SMBIOS configuration



Timer and HAL Extensions



We seem to be able to handle memory configuration (LPAE), but there will probably be some other problem. Oh yeah…







So, loading Windows so far only reaches this stage.





If a suitable system timer is not found, Windows refers to some supposed and invalid memory address



Windows will not boot if an interrupt controller or system timer is not found. System time can be registered using the GTDT table (ARM architecture table) or HAL extensions through the CSRT table.



iMX6ULL comes with three timers: iMX GPT (Generic Purpose Timer), EPIT (Enhanced Periodic Timer) and ARM Architectural Timer. The latter appeared only in iMX6UL / ULL, while previous iMX6 SoC systems worked on older kernels like the Cortex A15 without the support of an architectural timer. Microsoft implemented the EPIT HAL extension for the system timer, but it did not load at first due to a mismatch between the hardware identifier in the CSRT table and the system image (I downloaded the earlier FFU for iMX6 Solo). Therefore, when the timer is unavailable, Windows will desperately try to initialize the intended timer, and the system will crash due to invalid memory access.



The iMX6ULL documentation mentions an architectural timer, but without details about the initialization procedure. The timer counter can be initialized with EDK2, but the GIC PPI (Per Processor Interrupt) will not work correctly. However, Windows successfully initializes and uses the timer through the GTDT table.



UEFI currently uses the EPIT timer and disables it when transferring to Windows. In turn, Windows initializes the GPT timer. At some later point, UEFI can also switch to GPT with the proper initialization procedure.



Some peripherals require the HAL extension for the Smart DMA (SDMA) controller; it is not too difficult to download.



Show me how it works!



  [Security] 3rd party image [0] can be loaded after EndOfDxe: VenHw (0D51905B-B77E-452A-A2C0-ECA0CC8D514A, 004118020000000000) / USB (0x0.0x0) / USB (0x2.0x0) / HD (1, GPT, F9ADAEA9-E8DE-4291-B191-5DABA6DC1215.0x800.0x100000) / \ efi \ boot \ bootarm.efi.
  InstallProtocolInterface: 5B1B31A1-9562-11D2-8E3F-00A0C969723B 8F257028
  ConvertPages: failed to find range 10000000 - 100EEFFF
  Loading driver at 0x0008E9D6000 EntryPoint = 0x0008E9E7511 bootmgfw.efi
  InstallProtocolInterface: BC62157E-3E33-4FEC-9920-2D3B36D750DF 8F28EB10
  ProtectUefiImageCommon - 0x8F257028
  0x000000008E9D6000 - 0x00000000000EF000
  InstallProtocolInterface: 752F3136-4E16-4FDC-A22A-E5F46812F4CA 8FBFF88C
  ConvertPages: failed to find range 102000 - 102FFF
  Disabling EPIT timer on ExitBootServicesEventSetUefiImageMemoryAttributes - 0x000000008F78A000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F787000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F784000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F77F000 - 0x0000000000005000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F77C000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F779000 - 0x0000000000003000 (0x0000000000000008) 


If you wonder how slowly it loads, then about three and a half minutes.



Video at accelerated speed 2x:





Where is Secure Boot and TPM?



This is actually optional. But since OP-TEE supports iMX6 / 7/8, you can run Secure Monitor in TrustZone (TZ) and implement these services through calls (Secure Monitor Calls) from EL1 / PL1.



In fact, the official implementation of iMX Windows IoT comes with OP-TEE, but I ignored it for the sake of saving memory.



What about drivers?



The Windows 10 IoT BSP repository contains many drivers for iMX6 / 7/8. The USB driver works out of the box, as already mentioned. The calculator also needs touchscreen drivers and keyboards.



They are available in the Linux kernel tree, so it should not be too difficult to port them to Windows.



Can I download Windows RT 8.1?



Possibly . Update: Windows RT 8.1 will not boot, only later versions. Windows PE will not boot in ramdisk mode because 256 MB of memory is not enough. I could not start the flat boot mode, after listing the devices (including the USB drive) it enters into some kind of cycle without further initialization.





HP Prime G2 loaded Windows, which launched a calculator application





Notepad on calculator





Notepad on calculator is trying to send text to print.



But I want to boot Linux too!



There are two options:





Download Linux via GRUB or directly from EFISTUB. Everything is loading normally, here is a fragment of the log:



  EFI stub: Exiting boot services and installing virtual address map ...
  Disabling EPIT timer on ExitBootServicesEventSetUefiImageMemoryAttributes - 0x000000008F97B000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F978000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F973000 - 0x0000000000005000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F970000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F96D000 - 0x0000000000003000 (0x0000000000000008)
  SetUefiImageMemoryAttributes - 0x000000008F96A000 - 0x0000000000003000 (0x0000000000000008)
  Booting Linux on physical CPU 0x0
  Linux version 4.14.98-g371433a62906-dirty (imbushuo @ bc-macbookpro) (gcc version 7.4.1 20181213 [linaro-7.4-2019.02 revision 56ec6f6b99cc167ff0c2f8e1a2eed33b1edc85d4] (Linaro GCC 7.4-2019.02): # 2 PREEM 29 EST 2019
  CPU: ARMv7 Processor [410fc075] revision 5 (ARMv7), cr = 10c53c7d
  CPU: div instructions available: patching division code
  CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
  OF: fdt: Machine model: HP Prime G2 Calculator
  Memory policy: Data cache writeback
  efi: Getting EFI parameters from FDT:
  efi: EFI v2.70 by EDK II
  efi: ACPI 2.0 = 0x8f49b000 SMBIOS = 0x8f9a8000 SMBIOS 3.0 = 0x8f9a6000
  OF: reserved mem: failed to allocate memory for node 'linux, cma'
  CPU: All CPU (s) started in SVC mode.
  Built 1 zonelists, mobility grouping on.  Total pages: 64516
  Kernel command line: zImage.efi root = / dev / ram0 rw initrd = / rootfs.cpio.gz dtb = / imx6ull-14x14-prime.dtb 


If you use the NXP Linux configuration, this will crash the kernel because it reads the initrd memory address from the device tree or some predefined configuration parameters, and of course, initrd is loaded somewhere else in UEFI. It is necessary to remove these parameters and make the configuration more universal.



But why?



People talk about running Windows on different devices, so I want to troll them before the end of the year.



What about other projects? What's next?



The work will continue. You also need to implement some drivers, achieve UEFI boot with built-in NAND, implement the UEFI boot user-friendly interface for the calculator, and study the possibility of loading the HP PPL stock operating system from my UEFI.



All Articles