aarch64-laptops / debian-cdimage

79 stars 11 forks source link

Samsung Galaxy Book2 (SM-W737Y) snapdragon 850 #11

Open iam-TJ opened 3 years ago

iam-TJ commented 3 years ago

I've been doing some initial investigations on getting this system to boot GNU/Linux.

Currently starts grub2 successfully but fails at:

EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services and installing virtual address map...

Added debug to kernel command-line but do not see any messages from Linux until, after about 10 seconds, it resets. (I'll try earlyprintk later).

I have some time available to work on this so it'd be great if you could point me to any documentation on what my next steps are or catch me on IRC.

This device is quite easy to prepare.

In Windows hold down a Shift key whilst restarting from Windows power menu. This results in a light-blue background with "Choose an option". Choose "Troubleshoot" which results in another menu, choose "Advanced" and finally choose "UEFI Firmware Settings". That leads to a "Restart to change UEFI firmware settings" message and "Restart" button.

PC restarts into a 'traditional' text-only interface with multiple tabs "SysInfo", "Advanced", "Security", "Boot", "Exit"

Use "Boot" menu to set "Secure Boot Control" to "Disabled". You might want to also enable "PXE OPROM" in case we figure out how to achieve a network boot. "Advanced" menu only displays the Purchase Date!

"SysInfo" shows:

Storage Device: UFS SAMSUNG KLUDG4U1EA-B0C1 128GB

CPU Vendor: Qualcomm
CPU Type: SDM850
CPU Speed: 2400 MHz

Total Memory: 4096 MB

BIOS Version: P01AHG.007

Product Name: Galaxy Book2
Family Name: Galaxy Book Series

SKU Number: GALAXY A5A5-PAHG
Serial Number: 1PMUR52M70002E  

Choose "Exit" followed by ""Save Changes and Reset"

As soon as the "Samsung Galaxy Book2" splash screen shows start tapping the F10 key to get the manual boot selection menu. A hybrid ISO image on USB will show up as three items:

UEFI: USB CD/DVD Drive
UEFI: USB Hard Drive CD/DVD Drive
UEFI: USB Hard Drive

All of them will lead to grub2 boot menu

mothenjoyer69 commented 2 years ago

Absolutely ancient issue so my apologies for reviving it, but did you ever do anything more on this? More specifically, did you ever have success with BIOS Version P02AHG.005? Having a lot of trouble getting any USB to be recognized...

gyhmz commented 2 years ago

Absolutely ancient issue so my apologies for reviving it, but did you ever do anything more on this? More specifically, did you ever have success with BIOS Version P02AHG.005? Having a lot of trouble getting any USB to be recognized...

May be It's a bug in the firmware? My galaxy book2 is P02AHF.005 . I sometimes have the same problem, but when I meet this problem ,I just reboot it, and usb shows up in boot menu. Maybe you can try downgrade the rom? I have dumped 3 roms with two different versions(p02ahf p00ahe).

iam-TJ commented 2 years ago

I've just pulled this device out of cold storage and thought I'd check on progress. I found that mainline kernel has now added a Device Tree patch to support this model (SM-W737)!

commit d4b341269efb3c7fb37747064f7381c21dd7b983
Author: Xilin Wu <wuxilin123@gmail.com>
Date:   Wed Feb 23 22:51:32 2022 +0800

    arm64: dts: qcom: Add support for Samsung Galaxy Book2

    Add support for Samsung Galaxy Book2 (W737) tablets.

    Currently working features:
    - Bootloader preconfigured display at 1280p
    - UFS
    - Wacom Digitizer
    - Two USB 3 ports
    - Sound
    - Bluetooth
    - Wi-Fi

So I'll build v5.19 for arm64 and integrate into a Debian Bullseye image and see how it goes.

mothenjoyer69 commented 2 years ago

I've just pulled this device out of cold storage and thought I'd check on progress. I found that mainline kernel has now added a Device Tree patch to support this model (SM-W737)!

commit d4b341269efb3c7fb37747064f7381c21dd7b983
Author: Xilin Wu <wuxilin123@gmail.com>
Date:   Wed Feb 23 22:51:32 2022 +0800

    arm64: dts: qcom: Add support for Samsung Galaxy Book2

    Add support for Samsung Galaxy Book2 (W737) tablets.

    Currently working features:
    - Bootloader preconfigured display at 1280p
    - UFS
    - Wacom Digitizer
    - Two USB 3 ports
    - Sound
    - Bluetooth
    - Wi-Fi

So I'll build v5.19 for arm64 and integrate into a Debian Bullseye image and see how it goes.

I had some pretty decent luck with my Galaxy Book 2; it has ended up bricking itself, I'm still looking into the why, but I have a Thomson Neo Z3 (another SDM850 notebook) on the way. The biggest roadblock with the Galaxy Book 2 was making it consistently and reliably see boot media, so if you figure out why its so painful let me know :P

If you run into any other issues, too, let me know. Might be able to lend a hand

iam-TJ commented 2 years ago

@mothenjoyer69 Thanks; anything you can tell me about your experience (especially the 'little' details stuff) would help - I have to start from scratch because I cannot now recall what I did back in February 2021 when I opened this issue!

So far I've built a v5.19 kernel with the ARM64 Qualcom platform support enabled and am currently creating a bootable Debian Bullseye image on USB media. I cannot even recall now how I attached the boot media - presumably via one of the USB-C ports!

I did wonder if I'd tried a PXE boot until realising there isn't an Ethernet port, duh! (I fo now have a USB-C dock with an Ethernet port but without the UEFI drivers that wouldn't help).

On the USB device I originally used (fortunately kept in the box with the device) I noticed I'd added the Taincore EDK 2 shellaarch64.efi but like an idiot over-wrote that whilst preparing the new up-to-date Bullseye image!

iam-TJ commented 2 years ago

Absolutely ancient issue so my apologies for reviving it, but did you ever do anything more on this? More specifically, did you ever have success with BIOS Version P02AHG.005? Having a lot of trouble getting any USB to be recognized...

Thought initially it was my VM-created/proved bootable install (not ISO installer image) that works in a VM. I sometimes saw my image listed in the F10 manual boot device selection menu as "USB Hard Disk" but so far not got it to boot!

Just fetched debian-unstable-arm64-DVD-1_20210314.iso and having problems with that.

I may be having similar failures to you after allowing the damned thing to update to BIOS (!) Version P02AHG.005 and possibly since then the "USB Hard Disk" is not showing up :(

iam-TJ commented 2 years ago

Unless there is some merry dance or incantation required to get the UEFI to recognise the USB device, I suspect Lenovo removed the XHCI or USB Mass Storage UEFI driver from the firmware. That really breaks the existing functionality in serious way; Even Windows is now stuffed!

iam-TJ commented 2 years ago

OK - I just got it back! I removed the ISO image from the USB and replaced it with a single GPT partition (partition #1 if that is important) with FAT-16 512MB file-system named "EFI". Into that I did:

ISO="debian-unstable-arm64-DVD-1_20210314.iso"
wget https://github.com/aarch64-laptops/debian-cdimage/releases/download/v0.4/${ISO}
losetup -P --show -f ${ISO}
mkdir /mnt/iso
mount /dev/loop0 /mnt/iso

USB="/dev/sde"
sgdisk --zap-all ${USB}
sgdisk --new=1:0:+512M ${USB}
sgdisk --typecode=1:ef00 ${USB}
sgdisk --change-name=1:EFI ${USB}
mkfs.vfat -F 16 -n EFI ${USB}1
mkdir /mnt/usb
mount ${USB}1 /mnt/usb
mkdir -p /mnt/usb/EFI/BOOT
cp /mnt/iso/EFI/shell/Shell.efi /mnt/usb/EFI/BOOT/BOOTAA64.EFI
umount /mnt/usb

Upon inserting into the Book2's upper USB-C socket (in case that is important!) and rebooting, tapping the F10 key whilst the splash screen is displayed, I now have it at the top of the list:

UEFI: USB Hard Drive
Windows Boot Manager
UEFI: Unknown Device
UEFI: Hard Drive
UEFI Unknown Device
Enter Microsoft Recovery
Enter Setup
Enter QR Mode

Selecting it boots to the "UEFI Hard Drive":

Shell>

I'll build up the image from this point, adding one stage at a time, starting with GRUB.

I'll also try to figure out what particular part of the data layout of the boot device is critical to success.

iam-TJ commented 2 years ago

I'm going to leave some updates and exact commands I'm using as I progress otherwise I may forget key stages; but also to share with anyone else who comes after me and wants to reproduce this work.

I've now got it booting into GRUB's first stage (Core Image, the EFI file). I discovered two issues along the way. On the ISO shipped by this project /EFI/boot/bootaa64.efi is GRUB's core image but is missing the ext file system driver (only has vfat) so when I used it to try to bootstrap my USB installation it couldn't access the ext4 file-system. The second issue is bootaa64.efi from the Debian Bullseye arm64 install is actually shimaa64.efi and this file puts the PC into a boot loop (so I do away with that and use a copy of grubaa64.efi from the installed Debian image because it has included the required file-system drivers).

Prerequisites for this work:

# optional but can be useful to quickly examine source-code of any package via "apt-get source $package"
cat << EOT > /etc/apt/sources.list.d/sourcecode.list
deb-src https://deb.debian.org/debian $(lsb_release -sc) main non-free contrib
deb-src https://deb.debian.org/debian-security $(lsb_release -sc)-security main non-free contrib
EOT

apt update

apt install qemu-system-arm # aarch64 support in QEMU/libvirt
apt install qemu-utils # for qemu-nbd
apt install qemu-efi-aarch64 # UEFI firmware for QEMU aarch64 virtual machines
apt install virt-manager # GUI for libvirt and QEMU virtual machines
apt install crossbuild-essential-arm64 # for building aarch64 binaries on amd64
apt-get  build-dep linux # so the kernel build will have all its dependencies satisfied

(I think that's everything but if you hit obstacles ping me with details)

I always use a separate partition and file-system for /boot/ so that it can accommodate LUKS encryption to protect GRUB, kernel and initramfs files. So there are three partitions: EFI System Partition, /boot/, and the last for LVM.

# sgdisk --print /dev/sdf
Disk /dev/sdf: 60604416 sectors, 28.9 GiB
Model: DataTraveler 3.0
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): FE3296BD-A617-4546-9A95-F887A8CD74A4
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 60604382
Partitions will be aligned on 2-sector boundaries
Total free space is 0 sectors (0 bytes)

Number  Start (sector)    End (sector)  Size       Code  Name
   1              34         1048609   512.0 MiB   EF00  EFI system partition
   2         1048610         2621473   768.0 MiB   8301  
   3         2621474        60604382   27.6 GiB    8300

I used the plain Debian debian-11.4.0-arm64-DVD-1.iso and an aarch64 QEMU virtual machine Bullseye-aarch64 to make an installation into a qcow2 image file of a slightly smaller size than the USB storage I'm working with (~ 29GiB) with the LVM VG name galaxybook2-vg. (smaller in order to avoid problems if this image is slightly larger than the USB and causes the backup GPT at the end of the device to be truncated when written into the USB).

I then shut down the guest and use qemu-nbd to create block devices from that image and mount its file-systems.

T="/target.nbd0"
qemu-nbd -c /dev/nbd0 /var/lib/libvirt/images/Bullseye-aarch64.qcow2
kpartx -a /dev/nbd0
vgchange --activate y galaxybook2-vg
mkdir ${T}
mount /dev/galaxybook2-vg/root ${T}
mount -t proc proc /${T}/proc
mount -t devtmpfs udev ${T}/dev
mount -t devpts devpts ${T}/dev/pts
mount -t sysfs sysfs ${T}/sys
chroot ${T} mount -a

Separately I've cross-built the latest Linux v5.19 with the arm64 default config:

cd /srv/NAS/SourceCode/linux
export BUILD_DEBUG_PKG_DISABLE=1
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=../builds/linux-arm64   defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=../builds/linux-arm64 -j16  bindeb-pkg
$ ls -1 ../builds/linux*arm64.deb
../builds/linux-headers-5.19.0-00004-gc8767954e8ef_5.19.0-00004-gc8767954e8ef-1_arm64.deb
../builds/linux-image-5.19.0-00004-gc8767954e8ef_5.19.0-00004-gc8767954e8ef-1_arm64.deb
../builds/linux-libc-dev_5.19.0-00004-gc8767954e8ef-1_arm64.deb

I copy the three .deb files into the chroot so I can install them (note I do NOT build the debug symbol package because it takes too long and is over 1GB! - see my trivial build system patch that uses BUILD_DEBUG_PKG_DISABLE to make that optional). linux-bindeb-debug-package-optional.diff.txt

cp ../builds/linux*arm64.deb ${T}/tmp/
chroot ${T} dpkg -i /tmp/*.deb

And if it isn't done automatically in the previous step make sure GRUB knows about the new kernel:

chroot ${T} update-grub

Once this is done it's time to test it in the virtual machine so everything has to be unmounted and detached:

cd /
umount --lazy --recursive ${T}
qemu-nbd -d /dev/nbd0

Now reboot the VM and check it uses kernel v5.19 and starts correctly. If so, stop the guest and copy the image to USB (in my case its usually /dev/sdf):

qemu-nbd -c /dev/nbd0 /var/lib/libvirt/images/Bullseye-aarch64.qcow2

At this point the VG may have been discovered and the LVs opened. We need to close those before proceeding with the clone/copy:

vgchange --activate n galaxybook2-vg

USB="/dev/sdf"
dd if=/dev/nbd0 of=${USB} bs=16M status=progress conv=fsync
kpartx -a ${USB}

Now we need to make the identical clone VG in partition 3 of the USB unique BUT, because there are many configuration files with that name in, we instead change the original version (whilst both are on the same system at the same time, to avoid conflicts):

vgimportclone /dev/nbd0p3

At this point the LVM UUIDs are again unique and the original is now called galaxybook2-vg1.

Then move the USB to the PC and test!

iam-TJ commented 2 years ago

Well, currently I'm back to the original report... so some form of progress!

EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services

I tried various alternatives for the kernel efi= parameter but didn't visibily progress.

efi=            [EFI]
                        Format: { "debug", "disable_early_pci_dma",
                                  "nochunk", "noruntime", "nosoftreserve",
                                  "novamap", "no_disable_early_pci_dma" }
                        debug: enable misc debug output.
                        disable_early_pci_dma: disable the busmaster bit on all
                        PCI bridges while in the EFI boot stub.
                        nochunk: disable reading files in "chunks" in the EFI
                        boot stub, as chunking can cause problems with some
                        firmware implementations.
                        noruntime : disable EFI runtime services support
                        nosoftreserve: The EFI_MEMORY_SP (Specific Purpose)
                        attribute may cause the kernel to reserve the
                        memory range for a memory mapping driver to
                        claim. Specify efi=nosoftreserve to disable this
                        reservation and treat the memory by its base type
                        (i.e. EFI_CONVENTIONAL_MEMORY / "System RAM").
                        novamap: do not call SetVirtualAddressMap().
                        no_disable_early_pci_dma: Leave the busmaster bit set
                        on all PCI bridges while in the EFI boot stub

So I decided to heavily instrument (read: add print statements everywhere!) the kernel's EFI stub code at drivers/firmware/efi/libstub/fdt.c (patch linux-efi-fdt-debug.diff.txt E.g:

diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c
index fe567be0f118..e920650c2cad 100644
--- a/drivers/firmware/efi/libstub/fdt.c
+++ b/drivers/firmware/efi/libstub/fdt.c
@@ -274,24 +274,27 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
        efi_info("Exiting boot services...\n");

        map.map = &memory_map;
+       efi_info("Calling efi_allocate_pages()\n");
        status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, ULONG_MAX);
        if (status != EFI_SUCCESS) {
                efi_err("Unable to allocate memory for new device tree.\n");
                goto fail;
        }
-
+       efi_info("Returned from efi_allocate_pages()\n");
        /*
         * Now that we have done our final memory allocation (and free)
         * we can get the memory map key needed for exit_boot_services().
         */
+       efi_info("Calling efi_get_memory_map()\n");
        status = efi_get_memory_map(&map);
        if (status != EFI_SUCCESS)
                goto fail_free_new_fdt;
-
+       efi_info("Returned from efi_get_memory_map()\n");
+       efi_info("Calling update_fdt()\n");
...

There's more in the patch.

Now I've been sat waiting for many hours whilst a package update is in progress - stupidly I started it via a chroot on amd64 that is using qemu-aarch64-user emulation and writing to the USB device (which is USB3.0) but is going very slow. Currently 7 hours in and apt progress shows 33% so it could be a day before I can proceed!

Note to self: always apply updates in the VM guest with the qcow2 backing file then simply dd or rsync them onto the USB!

iam-TJ commented 2 years ago

15:30 and the package installs finally completed! Booted the Book2 with the patched kernel and can see that efi_exit_boot_services() isn't returning to the caller:

EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services...
EFI stub: Calling efi_allocate_pages()
EFI stub: Returned from efi_allocate_pages()
EFI stub: Calling efi_get_memory_map()
EFI stub: Returned from efi_get_memory_map()
EFI stub: Calling update_fdt()
EFI stub: Returned from update_fdt()
EFI stub: Calling efi_exit_boot_services()
iam-TJ commented 2 years ago

I've added more messages and switched to using efi_debug() and passing efi=debug on kernel command-line. linux-efi-fdt-debug.02.diff.txt I'm seeing (transcribed from a video capture):

EFI stub: Using DTB from configuration table
EFI stub: DEBUG: Entering allocate_new_fdt_and_exit_boot()
EFI stub: Exiting boot services...
EFI stub: DEBUG: Calling efi_allocate_pages()
EFI stub: DEBUG: Returned from efi_allocate_pages()
EFI stub: DEBUG: Calling efi_get_memory_map()
EFI stub: DEBUG: Returned from efi_get_memory_map()
EFI stub: DEBUG: Calling update_fdt()
EFI stub: DEBUG: Returned from update_fdt()
EFI stub: DEBUG: Calling efi_exit_boot_services()
EFI stub: DEBUG: Entered efi_Exit_boot_services()
EFI stub: DEBUG: Calling efi_get_memory_map()
EFI stub: DEBUG: Calling priv_func()
EFI stub: DEBUG: Calling efi_bs_call() with exit_boot_services
EFI stub: DEBUG: efi_bs_call() returned 2 (EFI_INVALID_PARAMETER)
EFI stub: DEBUG: Calling efi_bs_call() with get_memory_map
EFI stub: DEBUG: Calling priv_func() again
EFI stub: DEBUG: Calling efi_bs_call() with exit_boot_services, again!
EFI stub: DEBUG: fail: efi_exit_boot_services() returns 2
EFI stub: DEBUG: Returned from efi_exit_boot_services()
EFI stub: ERROR: Exit boot services failed.
EFI stub: DEBUG: fail_free_new_fdt: status=2
EFI stub: DEBUG: fail: status=2
EFI stub: ERROR: Failed to update FDT and exit boot services

At which point the screen is 'almost' cleared - it seems to return to a scrambled version of the previous Debian menu. The blue activity light on the Book2 continues to pulse slowly but there's no further interaction or progress and it requires a hard power off (holding the power button in and then releasing after about 10 seconds).

iam-TJ commented 2 years ago

Focusing on EFI stub: DEBUG: efi_bs_call() returned 2 (EFI_INVALID_PARAMETER) I've been looking at the EDK 2 source-code for CoreExitBootServices() in DxeMain.c

The Lenovo/Aptio (American Megatrends) firmware may be slightly different but in my experience of hacking on UEFI for the last decade many proprietary firmwares are built on top of EDK so we should be able to infer some things from looking at the EDK source-code.

I want to discover what is causing the EFI_INVALID_PARAMETER return code.

include/linux/efi.h:33:#define EFI_INVALID_PARAMETER    ( 2 | (1UL << (BITS_PER_LONG-1)))

Fortunately there is only one function where the return status of ExitBootServices() is set:

EFI_STATUS
EFIAPI
CoreExitBootServices (
  IN EFI_HANDLE  ImageHandle,
  IN UINTN       MapKey
  )
{
  EFI_STATUS  Status;

  //
  // Disable Timer
  //
  gTimer->SetTimerPeriod (gTimer, 0);

  //
  // Terminate memory services if the MapKey matches
  //
  Status = CoreTerminateMemoryMap (MapKey);
  if (EFI_ERROR (Status)) {
    //
    // Notify other drivers that ExitBootServices fail
    //
    CoreNotifySignalList (&gEventExitBootServicesFailedGuid);
    return Status;
  }
...

CoreTerminateMemoryMap()

EFI_STATUS
CoreTerminateMemoryMap (
  IN UINTN  MapKey
  )
{
  EFI_STATUS  Status;
  LIST_ENTRY  *Link;
  MEMORY_MAP  *Entry;

  Status = EFI_SUCCESS;

  CoreAcquireMemoryLock ();

  if (MapKey == mMemoryMapKey) {
    //
    // Make sure the memory map is following all the construction rules
    // This is the last chance we will be able to display any messages on
    // the  console devices.
    //

    for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {
      Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
      if (Entry->Type < EfiMaxMemoryType) {
        if (mMemoryTypeStatistics[Entry->Type].Runtime) {
          ASSERT (Entry->Type != EfiACPIReclaimMemory);
          ASSERT (Entry->Type != EfiACPIMemoryNVS);
          if ((Entry->Start & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
            DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
            Status =  EFI_INVALID_PARAMETER;
            goto Done;
          }

          if (((Entry->End + 1) & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
            DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
            Status =  EFI_INVALID_PARAMETER;
            goto Done;
          }
        }
      }
    }

    //
    // The map key they gave us matches what we expect. Fall through and
    // return success. In an ideal world we would clear out all of
    // EfiBootServicesCode and EfiBootServicesData. However this function
    // is not the last one called by ExitBootServices(), so we have to
    // preserve the memory contents.
    //
  } else {
    Status = EFI_INVALID_PARAMETER;
  }

Done:
  CoreReleaseMemoryLock ();

  return Status;
}

The interesting parts there are "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n" and the else clause when if (MapKey == mMemoryMapKey) fails to be true.

Now to figure out the easier of the two - the MapKey.

iam-TJ commented 2 years ago

Unfortunately, looks like an alignment issue. I've modified the debug patch to remove messages I know are no longer needed and added more reporting of the content of the map before and after functions that affect it (log transcribed from video): linux-efi-fdt-debug.03.diff.txt

EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: DEBUG: Entering allocate_new_fdt_and_exit_boot()
EFI stub: Exiting boot services...
EFI stub: DEBUG: Calling efi_exit_boot_services() with map:
EFI stub: DEBUG: efi_boot_memmap = {map=0x000000009ffce870 map_size=0xa20 desc_size=0x30 desc_ver=0x1
 key_ptr=0x000000009ffce868 *key_ptr=0x2b2c buff_size=0xc90 }
EFI stub: DEBUG: Entered efi_exit_boot_services()
EFI stub: DEBUG: Memory map before calling priv_func():
EFI stub: DEBUG: efi_boot_memmap = {map=0x000000009ffce870 map_size=0xa20 desc_size=0x30 desc_ver=0x1
 key_ptr=0x000000009ffce868 *key_ptr=0x2b2c buff_size=0xc90 }
EFI stub: DEBUG: Memory map after calling priv_func():
EFI stub: DEBUG: efi_boot_memmap = {map=0x000000009ffce870 map_size=0xa20 desc_size=0x30 desc_ver=0x1
 key_ptr=0x000000009ffce868 *key_ptr=0x2b2c buff_size=0xc90 }
EFI stub: DEBUG: Calling efi_bs_call(exit_boot_services, 0x00000000fcb87c98, 0x2b2c)
EFI stub: DEBUG: efi_bs_call() returned -9223372036854775806 (EFI_INVALID_PARAMETER)
EFI stub: DEBUG: Calling efi_bs_call() with get_memory_map
EFI stub: DEBUG: Memory map after calling get_memory_map() again:
EFI stub: DEBUG: efi_boot_memmap = {map=0x000000009ffce870 map_size=0xa20 desc_size=0x30 desc_ver=0x1
 key_ptr=0x000000009ffce868 *key_ptr=0x2b6e buff_size=0xc90 }
EFI stub: DEBUG: Calling priv_func() again
EFI stub: DEBUG: Memory map after calling priv_func() again:
EFI stub: DEBUG: efi_boot_memmap = {map=0x000000009ffce870 map_size=0xa20 desc_size=0x30 desc_ver=0x1
 key_ptr=0x000000009ffce868 *key_ptr=0x2b6e buff_size=0xc90 }
EFI stub: DEBUG: Calling (again!) efi_bs_call(exit_boot_services, 0x00000000fcb87c98, 0x2b6e)
EFI stub: DEBUG: fail: efi_exit_boot_services() returns -9223372036854775806
EFI stub: DEBUG: Returned from efi_Exit_boot_services()
EFI stub: ERROR: Exit boot services failed.
EFI stub: DEBUG: fail_free_new_fdt: status= -9223372036854775806
EFI stub: DEBUG: fail: status= -9223372036854775806
EFI stub: DEBUG: Busy Wait so you can read the debug messages!

So what is the allocation alignment? CoreTerminateMemoryMap() is testing against RUNTIME_PAGE_ALLOCATION_GRANULARITY which is set in EDK (for ARM64) at:

edk2/MdePkg/Include/AArch64/ProcessorBind.h:164:#define RUNTIME_PAGE_ALLOCATION_GRANULARITY  (0x10000)

So that is on boundaries of 65536 bytes, 64KB, (16 bit).

If the reports above (map=0x000000009ffce870) are what is being tested (it's slightly unclear what the EDK code is testing) then it definitely is not on a 64KB boundary.

iam-TJ commented 2 years ago

I began to wonder if the Device Tree binding was somehow at fault here so I took a look at sdm850-samsung-w737.dts and noticed there are several mentions of firmware-name with paths to required firmware files. The .dts file also has compatible = "samsung,w737", "qcom,sdm845"; which means these files can exist in one of two paths, (/usr)/lib/firmware/samsung/w737/ or {/usr}/lib/firmware/qcom/sdm845/.

$ grep firmware-name arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts
        firmware-name = "qcom/samsung/w737/qcadsp850.mbn";
        firmware-name = "qcom/samsung/w737/qccdsp850.mbn";
        firmware-name = "qcom/samsung/w737/ipa_fws.elf";
        firmware-name = "qcom/samsung/w737/qcdsp1v2850.mbn", "qcom/samsung/w737/qcdsp2850.mbn";
        firmware-name = "qcom/samsung/w737/qcvss850.mbn";

I do not think start-up has got far enough for those to matter but to ensure everything is in place I checked, and found most of the files are NOT in the installed image, NOT available in any Debian or Ubuntu firmware package, and NOT in the qcom/sdm845/ directory of linux-firmware repository.

I found the missing firmware files in the edk2-porting/sdm845-drivers repository. After cloning that I confirmed all the mentioned files are now on my system and then copied them into the bootable image:

$ sudo mkdir -p /${T}/usr/lib/firmware/qcom/sdm845
$ pushd /srv/NAS/Sunny/SourceCode/linux-firmware
$ sudo cp -v ./qcom/sdm845/* ${T}/usr/lib/firmware/qcom/sdm845/
'./qcom/sdm845/a630_zap.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/a630_zap.mbn'
'./qcom/sdm845/adsp.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/adsp.mbn'
'./qcom/sdm845/adspr.jsn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/adspr.jsn'
'./qcom/sdm845/adspua.jsn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/adspua.jsn'
'./qcom/sdm845/cdsp.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/cdsp.mbn'
'./qcom/sdm845/cdspr.jsn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/cdspr.jsn'
'./qcom/sdm845/mba.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/mba.mbn'
'./qcom/sdm845/modem.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/modem.mbn'
'./qcom/sdm845/modemuw.jsn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/modemuw.jsn'

$ pushd /srv/NAS/Sunny/SourceCode/linux

$ grep firmware-name arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts \
  | sed -n -e 's/[^"]*"\([^"]*\)"./\1\n/g p' \
  | sort | while read fw; do if [[ -n "$fw" ]]; then \
    find /usr/lib/firmware /srv/NAS/Sunny/SourceCode/linux-firmware /srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers -name "${fw##*/}" -ls; \
  fi; done
/srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers/qcipa850/ipa_fws.elf
/srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers/qcsubsys850/qcadsp850.mbn
/srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers/qcsubsys850/qccdsp850.mbn
/srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers/qcsubsys850/qcdsp1v2850.mbn
/srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers/qcsubsys850/qcdsp2850.mbn
/srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers/qcdx850/qcvss850.mbn

$ grep firmware-name arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts \
   | sed -n -e 's/[^"]*"\([^"]*\)"./\1\n/g p' \
   | sort | while read fw; do if [[ -n "$fw" ]]; then \
     find /usr/lib/firmware /srv/NAS/Sunny/SourceCode/linux-firmware /srv/NAS/Sunny/SourceCode/UEFI/sdm845-drivers -name "${fw##*/}" \
      -execdir  sudo cp -v {} ${T}/usr/lib/firmware/qcom/sdm845 \; ; \
   fi; done
[sudo] password for tj: 
'./ipa_fws.elf' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/ipa_fws.elf'
'./qcadsp850.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/qcadsp850.mbn'
'./qccdsp850.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/qccdsp850.mbn'
'./qcdsp1v2850.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/qcdsp1v2850.mbn'
'./qcdsp2850.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/qcdsp2850.mbn'
'./qcvss850.mbn' -> '/target.arm64/usr/lib/firmware/qcom/sdm845/qcvss850.mbn'

$ popd
$ popd
iam-TJ commented 2 years ago

Interesting discovery - when the boot fails and the PC returns to the GRUB menu I've thought until now that it was locked up, despite the blue LED pulsating, because it isn't responding to keyboard input. It turns out the keyboard may be disabled but the volume buttons are working to control up/down movement. Press to the left (nearest the power button) moves Up; press to the right moves Down. Not sure how to simulate pressing Enter though!

I had hoped disconnecting and reconnecting the keyboard might solve that but it doesn't.

iam-TJ commented 2 years ago

I've done some experiments with a direct boot (not via GRUB) into the Linux arch/arm64/boot/Image (since it is a valid EFI PXE executable) via the EDK 2 Shell. This still fails with or without a forced load of the DTB file:

# cp -v /srv/NAS/Sunny/SourceCode/builds/linux-arm64/arch/arm64/boot/Image /target.arm64/boot/efi/EFI/BOOT/LINUXAA64.EFI
# cp -v /srv/NAS/Sunny/SourceCode/builds/linux-arm64/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dtb /target.arm64/boot/efi/EFI/BOOT/

Make the shell the default loader (replaces GRUB's core image in the removable media path)

# cp /target.arm64/boot/efi/EFI/BOOT/{SHELL,BOOT}AA64.EFI

Boot the Book2 and after some initial scanning we get to the Shell> prompt. Now switch to the USB device, which in my case turns out to be FS2 and then start Linux with command-line options:

Shell> FS2:
FS2:> cd EFI\BOOT
FS2:\EFI\BOOT> LINUXAA64.EFI debug efi=debug dtb=/EFI/BOOT/sdm850-samsung-w737.tb

This generates the same messages as reported earlier with the slight difference that it reports loading the DTB file.

EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from command line
EFI stub: DEBUG: Entering allocate_new_fdt_and_exit_boot()
EFI stub: Exiting boot services...
...

Without the DTB loaded manually it reports an empty DTB which seems to indicate EFI did not pass the DTB pointer in memory as it is expected/supposed to do (booting via GRUB shows EFI stub: Using DTB from configuration table):

EFI stub: Booting Linux Kernel...
EFI stub: Generating empty DTB
EFI stub: DEBUG: Entering allocate_new_fdt_and_exit_boot()
EFI stub: Exiting boot services...
...

I even tried looping up to 10 times (see patch below) in case the comment in drivers/firmware/efi/libstub/efi-stub-helper.c::efi_exit_boot_services() was a clue:

                /*
                 * The memory map changed between efi_get_memory_map() and
                 * exit_boot_services().  Per the UEFI Spec v2.6, Section 6.4:
                 * EFI_BOOT_SERVICES.ExitBootServices we need to get the
                 * updated map, and try again.  The spec implies one retry
                 * should be sufficent, which is confirmed against the EDK2
                 * implementation.  Per the spec, we can only invoke
                 * get_memory_map() and exit_boot_services() - we cannot alloc
                 * so efi_get_memory_map() cannot be used, and we must reuse
                 * the buffer.  For all practical purposes, the headroom in the
                 * buffer should account for any changes in the map so the call
                 * to get_memory_map() is expected to succeed here.
                 */

linux-efi-fdt-debug.06.diff.txt

iam-TJ commented 2 years ago

I've extracted the firmware images from the device and uncompressed an LZMA firmware image file contained in one of the block devices and confirmed this is using the EDK 2 as a basis. There are also several .cfg text files as well as image files used for the splash screen, battery status, .bin files containing various X509 certificates (used for SecureBoot), and more.

In case these are of interest to anyone else I've attached text files containing lists of the files and the results of file identifying their contents where possible.

FS0 is the internal view from the Shell. FS1 appears to be the raw compressed firmware image and associated files. I extracted that using binwalk and then dd | unlzma:

$ cd firmware.w737.fs1/
$ binwalk 9E21FD93-9C72-4C15-8C4B-E77F1DB2D792
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
24            0x18            LZMA compressed data, properties: 0x5D, dictionary size: 16777216 bytes, uncompressed size: 11768776 bytes

$ dd if=9E21FD93-9C72-4C15-8C4B-E77F1DB2D792 bs=1 skip=24 | unlzma > 9E21FD93-9C72-4C15-8C4B-E77F1DB2D792.unlzma

strings 9E21FD93-9C72-4C15-8C4B-E77F1DB2D792.unlzma  | grep '^[^ ]*\.c$' | sort -u > 9E21FD93-9C72-4C15-8C4B-E77F1DB2D792.strings.source-filenames.txt

samsung-w737.map.txt samsung-w737-filelist-FS0.txt samsung-w737-filelist-FS1.txt 9E21FD93-9C72-4C15-8C4B-E77F1DB2D792.strings.source-filenames.txt source-files-in-EDK2.txt

iam-TJ commented 2 years ago

I've made a bug report to the linux-efi sub-system at https://bugzilla.kernel.org/show_bug.cgi?id=216375

iam-TJ commented 2 years ago

I've now got it booting into the initrd.img shell; the solution is to simply ignore the EFI_INVALID_PARAMETER returned by exit_boot_services() and carry on!

iam-TJ commented 2 years ago

Still trying to solve the failure to exit_boot_services() due to return value being EFI_INVALID_PARAMETER.

Anyone else with this device that would be willing to do some comparison testing for me to be sure all Book2's (W737) with latest Lenovo firmware behave this way, please let me know.

All it'll need is a USB stick to boot from and I can provide a bootable image for download.

mothenjoyer69 commented 1 year ago

@iam-TJ sorry about the huge wait; ended up getting busy and I haven't had the time to touch the Galaxy Book 2. Feel free to shoot that bootable image my way!

mothenjoyer69 commented 1 year ago

After a bit of catching up and getting back into it, I've got a sometimes-it-boots, sometimes-it-doesn't kernel config + buildroot config setup that I need to fix up a bit. I've also got a crappy little utility script, so I'll push that to a repo for anyone who wants it. Apart from that, nothing really going much further. My experience is limited but I've got a few things to look into today, so I'll update you if I have any success.

On top of that, feel free to directly contact me via Matrix (@mothenjoyer69:matrix.org) or Discord (mothenjoyer69#7992) if you'd like.

iam-TJ commented 1 year ago

I paused my work hoping for some kind of serious input from full-time kernel devs that have long experience with the UEFI boot code but nothing came of that. I've emailed twice, on two separate email addresses, the person that authored the device-tree configuration but not had a reply:

commit d4b341269efb3c7fb37747064f7381c21dd7b983
Author: Xilin Wu <wuxilin123@gmail.com>
Date:   Wed Feb 23 22:51:32 2022 +0800

    arm64: dts: qcom: Add support for Samsung Galaxy Book2

And from looking at the AOSP/Android project where their work seemed to be focused I do not see evidence of a boot being achieved.

I'll do another build today just to be sure it hasn't fixed itself whilst being powered off, then create a simple UEFI boot image that just has UEFI boot loader, kernel, and initrd.img. If it'll get past that then any incremental work to bring up full hardware support will be just tinkering in comparison to solving the boot failure!

mothenjoyer69 commented 1 year ago

Hmm, that is understandable. That being said, this is a Google Drive hosted confirmed-working built kernel + small rootfs. This is from the original author of the mainline work, via Discord (unfortunately a very brief and fruitless conversation). It appears to be running a Xiaomi focused fork of the SDM845 kernel project. The images from aarch64-laptops can boot too, although they are massively broken in a few ways.

From the information I dug up, the UEFI implementation is broken in many ways, but with the correct patches applied, Grub can work. I have had success in the past with getting custom-built kernels to boot, even if its just for a few seconds, so I'm honestly unsure of what exactly is missing here.

iam-TJ commented 1 year ago

Yes; I did see that SDM845 project - I think that is where I focused initially but found that there was no clear history of the patches required nor record of what was seen. What is confusing/interesting/strange is his Device Tree patch should not be needed since the device passes the (assumed to be) correct device tree to boot-loader and kernel.

My work confirms that and I was intending, once it boots a little further, to capture that from memory and write it to a file so we can decompile it and compare with the kernel DTS commit to find out if they are identical - and improve the kernel's DTS if not.

As I said earlier, I did get the device to boot a few times but for those the firmware DTB wasn't passed in the UEFI boot structures. I've not been able to reproduce those earlier kernel starts either so have focused on solving the EFI_INVALID_PARAMETER from exit_boot_services().

iam-TJ commented 1 year ago

I've separated out my debug code into individual commits to make it easier to play about with it. All the different approaches are guarded with if (0) { ...} so to test them change to if (1) -

https://github.com/iam-TJ/linux/tree/efi-libstub-debug

iam-TJ commented 1 year ago

The MiniLinux-w737.7z you pointed to, when extracted into an EFI-SP on a USB device, does boot to a desktop!

uname -r
5.17.0-rc4-xiaomi-sdm845+

$ cat /proc/config.gz | gzip -d | grep LOCALVERSION
CONFIG_LOCALVERSION="xiaomi-sdm845"

It was built on Ubuntu 20.04 with GCC v9.3.

I'm trying to track down the kernel source for it - any clues? Possibly based on:

https://gitlab.com/sdm845-mainline/linux/-/tree/sdm845/5.17-rc4/arch/arm64/configs

iam-TJ commented 1 year ago

I attempted to compare the mainline v5.17rc4 default kernel config with that used by the MiniLinux image; I cleaned and sorted both config files then parsed them, separating out the options that are part of arch/arm64/configs/defconfig and the extra options. Unfortunately the differences are huge:

inc="/tmp/config.default"; extra="/tmp/config.extra";
default="../builds/linux-w737/config.5.17-rc4_defconfig";
w737="../builds/linux-w737/config.5.17.0-rc4-xiaomi-sdm845+";
while read cfg; do
  if ! grep -q "$cfg" "$default"; then
    target="$extra";
 else
    target="$inc";
 fi;
 echo "$cfg" >> "$target";
done < $w737

$ wc -l ../builds/linux-w737/config.5.17-rc4_defconfig  /tmp/config.*
  1234 ../builds/linux-w737/config.5.17-rc4_defconfig
   364 /tmp/config.default
  2600 /tmp/config.extra
iam-TJ commented 1 year ago

Focusing just on those settings related to EFI I first extracted them to separate files for the MiniLinux kernel and my recent v5.19 builds to see if I may be missing anything:

$ comm _EFI.config.5.19-tj  _EFI.config.5.17.0-rc4-xiaomi-sdm845+
                CONFIG_EFI_ARMSTUB_DTB_LOADER=y
        CONFIG_EFI_BOOTLOADER_CONTROL=y
        CONFIG_EFI_CAPSULE_LOADER=y
        CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
        CONFIG_EFI_EARLYCON=y
                CONFIG_EFI_ESRT=y
                CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
                CONFIG_EFI_GENERIC_STUB=y
                CONFIG_EFI_PARAMS_FROM_FDT=y
                CONFIG_EFI_PARTITION=y
                CONFIG_EFI_RUNTIME_WRAPPERS=y
                CONFIG_EFI_STUB=y
CONFIG_EFIVAR_FS=m
        CONFIG_EFIVAR_FS=y
                CONFIG_EFI_VARS_PSTORE=y
                CONFIG_EFI=y
                CONFIG_FB_EFI=y
        CONFIG_RTC_DRV_EFI=m

comm writes three columns; first is lines only in first file; second is lines only in second file; third is lines in both files. So my builds are currently not using:

        CONFIG_EFI_BOOTLOADER_CONTROL=y
        CONFIG_EFI_CAPSULE_LOADER=y
        CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
        CONFIG_EFI_EARLYCON=y
        CONFIG_RTC_DRV_EFI=m

And I have CONFIG_EFIVAR_FS set to build as a module.

CONFIG_EFI_EARLYCON=y isn't possible on ARM (Depends on: EFI [=y] && SERIAL_EARLYCON [=y] && !ARM && !IA64 - note the !ARM). I'll add the other options and retest.

mothenjoyer69 commented 1 year ago

Just to update for this thread: On top of the EFI issue @iam-TJ is debugging, I've gotten a userland working in TTY, however noticed that the bridge driver has no support for the dual channel DSI panel in the Galaxy Book 2. This is confirmed by a comment in the DTS. So, that's where I'm going to head with this.

strongtz commented 1 year ago

The MiniLinux-w737.7z you pointed to, when extracted into an EFI-SP on a USB device, does boot to a desktop!

uname -r
5.17.0-rc4-xiaomi-sdm845+

$ cat /proc/config.gz | gzip -d | grep LOCALVERSION
CONFIG_LOCALVERSION="xiaomi-sdm845"

It was built on Ubuntu 20.04 with GCC v9.3.

I'm trying to track down the kernel source for it - any clues? Possibly based on:

https://gitlab.com/sdm845-mainline/linux/-/tree/sdm845/5.17-rc4/arch/arm64/configs

Sorry for the late reply, I saw your email to me just now. Unfortunately I have no idea what's wrong either, thought it was maybe a grub related issue.... So I just stuck with the grub I sent in MiniLinux.

steev commented 1 year ago

Focusing just on those settings related to EFI I first extracted them to separate files for the MiniLinux kernel and my recent v5.19 builds to see if I may be missing anything:

$ comm _EFI.config.5.19-tj  _EFI.config.5.17.0-rc4-xiaomi-sdm845+
                CONFIG_EFI_ARMSTUB_DTB_LOADER=y
        CONFIG_EFI_BOOTLOADER_CONTROL=y
        CONFIG_EFI_CAPSULE_LOADER=y
        CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
        CONFIG_EFI_EARLYCON=y
                CONFIG_EFI_ESRT=y
                CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER=y
                CONFIG_EFI_GENERIC_STUB=y
                CONFIG_EFI_PARAMS_FROM_FDT=y
                CONFIG_EFI_PARTITION=y
                CONFIG_EFI_RUNTIME_WRAPPERS=y
                CONFIG_EFI_STUB=y
CONFIG_EFIVAR_FS=m
        CONFIG_EFIVAR_FS=y
                CONFIG_EFI_VARS_PSTORE=y
                CONFIG_EFI=y
                CONFIG_FB_EFI=y
        CONFIG_RTC_DRV_EFI=m

comm writes three columns; first is lines only in first file; second is lines only in second file; third is lines in both files. So my builds are currently not using:

        CONFIG_EFI_BOOTLOADER_CONTROL=y
        CONFIG_EFI_CAPSULE_LOADER=y
        CONFIG_EFI_CUSTOM_SSDT_OVERLAYS=y
        CONFIG_EFI_EARLYCON=y
        CONFIG_RTC_DRV_EFI=m

And I have CONFIG_EFIVAR_FS set to build as a module.

CONFIG_EFI_EARLYCON=y isn't possible on ARM (Depends on: EFI [=y] && SERIAL_EARLYCON [=y] && !ARM && !IA64 - note the !ARM). I'll add the other options and retest.

You should be able to because ARM64 != ARM; CONFIG_EFI_EARLYCON=y is set in my config for my C630.

lordkitsuna commented 1 year ago

has anyone found anything for this guy? i sadly have one sitting here wishing it was something other than windows. can barely run plex with windows eating up so much ram just to exist :<

mothenjoyer69 commented 1 year ago

has anyone found anything for this guy? i sadly have one sitting here wishing it was something other than windows. can barely run plex with windows eating up so much ram just to exist :<

Nothing has changed, as far as I've seen. The biggest blocker is that the DSI to eDP bridge driver is incomplete and missing support for the specific display in the Galaxy Book 2. I no longer have a Galaxy Book 2, so until I grab another I won't be able to do too much. I don't believe anyone else is actively working on the machine, either.

krrrak commented 4 months ago

refer to the guidance of another device with sdm850: https://github.com/calebccff/c630_bootstrap, I have booted archlinux. But after grub done its work, the display don't work anymore. I know it successfully booted into linux because it powered off after I typed poweroff.

mothenjoyer69 commented 4 months ago

refer to the guidance of another device with sdm850: https://github.com/calebccff/c630_bootstrap, I have booted archlinux. But after grub done its work, the display don't work anymore. I know it successfully booted into linux because it powered off after I typed poweroff.

Yes, as I mentioned in the last comment here prior to yours, the display will not work because the driver for the DSI to eDP bridge (SN65DSI86, if I recall correctly) is incomplete.

Until someone submits patches to complete the driver, this device is a lost cause.