Thursday, August 22, 2013

Upgrading to BIOS version A08 on Dell Sputnik

Upgrading the BIOS on a Dell XPS13 (Sputnik) is a huge pain in Linux. I work on Ubuntu 13.04 on my sputnik, so some of this may be specific to that version of Ubuntu. To summarize the procedure, I built a FreeDOS hard disk image and use that image to upgrade the BIOS. I had to use a hard disk image because the bios upgrade binary is bigger than a floppy. Here are the steps:
  1. wget http://www.freedos.org/download/download/fdbasecd.iso
  2. qemu-img create -f raw upgrade_bios.img 100M (you can use dd to do this also)
  3. qemu-system-x86_64 -hda upgrade_bios.img -cdrom fdbasecd.iso -boot d
  4. Install FreeDOS onto the disk image.
  5. Shutdown the VM.
  6. wget http://downloads.dell.com/FOLDER01438023M/1/L322XA08.exe
  7. Become root (su or sudo -s)
  8. kpartx -sav upgrade_bios.img (will create /dev/loop[0-9]\+ and /dev/mapper/loop[0-9]\+p1)
  9. mount /dev/mapper/loop0p1 /mnt
  10. mkdir /mnt/bios
  11. cp L322XA08.exe /mnt/bios
  12. umount /mnt
  13. kpartx -sd upgrade_bios.img
  14. cp upgrade_bios.img /boot
  15. apt-get install syslinux
  16. Add following a script in /etc/grub.d to add entries to grub to boot to the image using memdisk from syslinux. The entries should look something like the following:
    menuentry "Upgrade BIOS" {
       insmod part_msdos
       insmod ext2
       linux16 /usr/lib/syslinux/memdisk
       initrd16 /boot/upgrade_bios.img
    }
    For example, here's my /etc/grub.d/25_memdisk_for_bios_upgrade:
    #!/bin/sh set -e if [ -f /usr/lib/grub/grub-mkconfig_lib ]; then . /usr/lib/grub/grub-mkconfig_lib LX=linux16 else # no grub file, so we notify and exit gracefully echo "Cannot find grub config file, exiting." >&2 exit 0 fi # We need 16-bit boot, which isn't available on EFI. if [ -d /sys/firmware/efi ]; then exit 0 fi # We can't cope with loop-mounted devices here. case ${GRUB_DEVICE_BOOT} in /dev/loop/*|/dev/loop[0-9]) exit 0 ;; esac prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" if test -e /boot/upgrade_bios.img ; then FREEDOSPATH=$( make_system_path_relative_to_its_root "/boot/upgrade_bios.img" ) echo "Found BIOS upgrade image: $FREEDOSPATH" >&2 cat << EOF menuentry "Upgrade BIOS" { EOF printf '%s\n' "${prepare_boot_cache}" cat << EOF $LX /usr/lib/syslinux/memdisk initrd16 $FREEDOSPATH } EOF fi
  17. chmod 755 /etc/grub.d/25_memdisk_for_bios_upgrade
  18. update-grub
  19. Reboot computer and get into grub boot menu (in Ubuntu, you can hold Shift during the boot to for showing the grub menu)
  20. Select "Upgrade BIOS"
  21. Select 1st boot option from FreeDOS boot menu
  22. Wait for C:\> prompt
  23. cd BIOS
  24. Make sure your power is plugged in.
  25. run L322XA08.exe
  26. Wait for it to complete
  27. Reboot and celebrate if it works.
UPDATE (2013/10/19): Added script contents for /etc/grub.d/25_memdisk_for_bios_upgrade.

UPDATE (2013/11/09): Fixed the 25_memdisk_for_bios_upgrade script. Added some previously missing steps.

UPDATE (2013/12/21): Dell, if you ever read this, providing the baked freedos .img file with the BIOS upgrader inside as a download from your website would be super useful. Bonus points if you make the BIOS utility start with autoexec.bat and then restart the machine when it's done. That's exactly what I did to enable a similar image to be used to upgrade BIOSes on some Dell servers. It even worked over PXE.