func raspbianEnableUART(boot string) error {
	fmt.Printf("- Enabling console on UART on RPi3\n")
	f, err := os.OpenFile(filepath.Join(boot, "config.txt"), os.O_APPEND|os.O_WRONLY, 0666)
	if err != nil {
		return err
	}
	if _, err = f.WriteString(raspberryPi3UART); err != nil {
		return err
	}
	return f.Close()
}
raspbianEnableUART enables console on UART on RPi3.

This is only needed when debugging over serial, mainly to debug issues with
setup.sh.

https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=141195
package main  
import (
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"github.com/rekby/mbr"
	"golang.org/x/crypto/pbkdf2"
	"periph.io/x/bootstrap/img"
)
const oldRcLocal = "#!/bin/sh -e\n#\n# rc.local\n#\n# This script is executed at the end of each multiuser runlevel.\n# Make sure that the script will \"exit 0\" on success or any other\n# value on error.\n#\n# In order to enable or disable this script just change the execution\n# bits.\n#\n# By default this script does nothing.\n"
const denseRcLocal = "#!/bin/sh -e\nL=/var/log/firstboot.log;if [ ! -f $L ];then /boot/firstboot.sh%s 2>&1|tee $L;fi\n#"
const raspberryPi3UART = `
# Enable console on UART on RPi3
# https: 
[pi3]
enable_uart=1
[all]
`
const raspberryPiWPASupplicant = `country=%s
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
# Generated by https: 
network={
	ssid="%s"
	psk=%s
	key_mgmt=WPA-PSK
}
`
var (
	image        img.Image
	sshKey       = flag.String("ssh-key", img.FindPublicKey(), "ssh public key to use")
	email        = flag.String("email", "", "email address to forward root@localhost to")
	wifiCountry  = flag.String("wifi-country", img.GetCountry(), "Country setting for Wifi; affect usable bands")
	wifiSSID     = flag.String("wifi-ssid", "", "wifi ssid")
	wifiPass     = flag.String("wifi-pass", "", "wifi password")
	fiveInches   = flag.Bool("5inch", false, "Enable support for 5\" 800x480 display (Raspbian only)")
	forceUART    = flag.Bool("forceuart", false, "Enable console UART support (Raspbian only)")
	sdCard       = flag.String("sdcard", getDefaultSDCard(), getSDCardHelp())
	timeLocation = flag.String("time", img.GetTimeLocation(), "Location to use to define time")
	postScript   = flag.String("post", "", "Command to run after setup is done")
	v            = flag.Bool("v", false, "log verbosely")
)
var sdCardsFound = img.ListSDCards()
func init() {
	flag.Var(&image.Manufacturer, "manufacturer", img.ManufacturerHelp())
	flag.Var(&image.Board, "board", img.BoardHelp())
	flag.Var(&image.Distro, "distro", img.DistroHelp())
}
func getDefaultSDCard() string {
	if len(sdCardsFound) == 1 {
		return sdCardsFound[0]
	}
	return ""
}
func getSDCardHelp() string {
	if len(sdCardsFound) == 0 {
		return "Path to SDCard; be sure to insert one first"
	}
	if len(sdCardsFound) == 1 {
		return "Path to SDCard"
	}
	return fmt.Sprintf("Path to SDCard; one of %s", strings.Join(sdCardsFound, ","))
}
func copyFile(dst, src string, mode os.FileMode) error {
	fs, err := os.Open(src)
	if err != nil {
		return err
	}
	defer fs.Close()
	fd, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE, mode)
	if err != nil {
		return err
	}
	if _, err := io.Copy(fd, fs); err != nil {
		_ = fd.Close()
		return err
	}
	return fd.Close()
}
func modifyEXT4(img string) (bool, error) {
	fmt.Printf("- Modifying image %s\n", img)
	f, err := os.OpenFile(img, os.O_RDWR, 0666)
	if err != nil {
		return false, err
	}
	modified, err := modifyEXT4Inner(f)
	if err2 := f.Close(); err == nil {
		err = err2
	}
	return modified, err
}
type fileDisk struct {
	f    *os.File
	off  int64
	size int64
}
func (f *fileDisk) Close() error {
	return errors.New("abstraction layer error")
}
func (f *fileDisk) Len() int64 {
	return f.size
}
func (f *fileDisk) ReadAt(p []byte, off int64) (int, error) {
	if off+int64(len(p)) > f.size {
		return 0, io.EOF
	}
	return f.f.ReadAt(p, off+f.off)
}
func (f *fileDisk) SectorSize() int {
	return 512
}
func (f *fileDisk) WriteAt(p []byte, off int64) (int, error) {
	if off+int64(len(p)) > f.size {
		return 0, errors.New("overflow")
	}
	return f.f.WriteAt(p, off+f.off)
}
func modifyEXT4Inner(f *os.File) (bool, error) {
	m, err := mbr.Read(f)
	if err != nil {
		return false, fmt.Errorf("failed to read MBR: %w", err)
	}
	if err = m.Check(); err != nil {
		return false, err
	}
	rootpart := m.GetPartition(2)
	root := &fileDisk{f, int64(rootpart.GetLBAStart() * 512), int64(rootpart.GetLBALen() * 512)}
	offset := int64(0)
	prefix := []byte(oldRcLocal)
	buf := make([]byte, 512)
	for ; offset < root.Len(); offset += 512 {
		if _, err = root.ReadAt(buf, offset); err != nil {
			return false, fmt.Errorf("failed to read at offset %d while seaching for /etc/rc.local: %w", offset, err)
		}
		if bytes.Equal(buf[:len(prefix)], prefix) {
			log.Printf("found /etc/rc.local at offset %d", offset)
			break
		}
	}
	if offset >= root.Len() {
		return false, nil
	}
	content := fmt.Sprintf(denseRcLocal, firstBootArgs())
	copy(buf, content)
	log.Printf("Writing /etc/rc.local:\n%s", buf)
	_, err = root.WriteAt(buf, offset)
	return true, err
}
func firstBootArgs() string {
	args := " -t " + *timeLocation
	if len(*email) != 0 {
		args += " -e " + *email
	}
	if *fiveInches {
		args += " -5"
	}
	if len(*sshKey) != 0 {
		args += " -sk /boot/authorized_keys"
	}
	if image.Distro != img.Raspbian {
		args += " -wc " + *wifiCountry
		if len(*wifiSSID) != 0 {
			args += fmt.Sprintf(" -ws %q", *wifiSSID)
		}
		if len(*wifiPass) != 0 {
			args += fmt.Sprintf(" -wp %q", *wifiPass)
		}
	}
	if len(*postScript) != 0 {
		args += " -- /boot/" + filepath.Base(*postScript)
	}
	return args
}
func wpaPSK(passphrase, ssid string) string {
	return hex.EncodeToString(pbkdf2.Key([]byte(passphrase), []byte(ssid), 4096, 32, sha1.New))
}
func setupFirstBoot(boot string) error {
	fmt.Printf("- First boot setup script\n")
	if err := ioutil.WriteFile(filepath.Join(boot, "firstboot.sh"), img.GetSetupSH(), 0755); err != nil {
		return err
	}
	if len(*sshKey) != 0 {
		if err := copyFile(filepath.Join(boot, "authorized_keys"), *sshKey, 0644); err != nil {
			return err
		}
	}
	if len(*postScript) != 0 {
		if err := copyFile(filepath.Join(boot, filepath.Base(*postScript)), *postScript, 0755); err != nil {
			return err
		}
	}
	if image.Distro == img.Raspbian && len(*wifiSSID) != 0 {
		c := fmt.Sprintf(raspberryPiWPASupplicant, *wifiCountry, *wifiSSID, wpaPSK(*wifiPass, *wifiSSID))
		if err := ioutil.WriteFile(filepath.Join(boot, "wpa_supplicant.conf"), []byte(c), 0644); err != nil {
			return err
		}
	}
	return nil
}