diff -Nru goget-ubuntu-touch-0.12/debian/changelog goget-ubuntu-touch-0.16/debian/changelog --- goget-ubuntu-touch-0.12/debian/changelog 2015-02-17 19:43:17.000000000 +0000 +++ goget-ubuntu-touch-0.16/debian/changelog 2015-02-17 19:43:18.000000000 +0000 @@ -1,3 +1,35 @@ +goget-ubuntu-touch (0.16-0ubuntu1) vivid; urgency=medium + + * ubuntu-device-flash: oem part to allow for dtb overrides. + * debian/control: dep on fakeroot for ubuntu-device-flash. + + -- Sergio Schvezov Thu, 29 Jan 2015 15:23:27 -0300 + +goget-ubuntu-touch (0.15-0ubuntu1) vivid; urgency=medium + + [ Loïc Minier ] + * ubuntu-device-flash: fixed ftdfile -> fdtfile typo. + + [ Sergio Schvezov ] + * ubuntu-device-flash: + - future proof efi support for grub and provisioning boot partition. + - using test instead of load in snappy-commands.txt + + -- Sergio Schvezov Wed, 28 Jan 2015 19:53:33 -0300 + +goget-ubuntu-touch (0.14-0ubuntu1) vivid; urgency=medium + + * Partition sizing multiplier matters for the emulator disk. (LP: #1412495) + + -- Sergio Schvezov Wed, 21 Jan 2015 20:23:14 -0300 + +goget-ubuntu-touch (0.13-0ubuntu1) vivid; urgency=medium + + * Setting a fixed set of ssh host keys to create. + * Updating ubuntu-device-flash's manpage and code to generate it. + + -- Sergio Schvezov Mon, 19 Jan 2015 18:45:29 -0300 + goget-ubuntu-touch (0.12-0ubuntu1) vivid; urgency=medium * ubuntu-device-flash: diff -Nru goget-ubuntu-touch-0.12/debian/control goget-ubuntu-touch-0.16/debian/control --- goget-ubuntu-touch-0.12/debian/control 2015-02-17 19:43:17.000000000 +0000 +++ goget-ubuntu-touch-0.16/debian/control 2015-02-17 19:43:18.000000000 +0000 @@ -19,6 +19,7 @@ Architecture: any Depends: android-tools-adb, android-tools-fastboot, + fakeroot, kpartx, qemu-user-static, ${misc:Depends}, diff -Nru goget-ubuntu-touch-0.12/debian/ubuntu-device-flash.1 goget-ubuntu-touch-0.16/debian/ubuntu-device-flash.1 --- goget-ubuntu-touch-0.12/debian/ubuntu-device-flash.1 2015-02-17 19:43:17.000000000 +0000 +++ goget-ubuntu-touch-0.16/debian/ubuntu-device-flash.1 2015-02-17 19:43:18.000000000 +0000 @@ -1,68 +1,125 @@ -.TH UBUNTU-DEVICE-FLASH 1 - +.TH ubuntu-device-flash 1 "19 January 2015" .SH NAME -ubuntu-device-flash \- provision supported Nexus devices with Ubuntu - +ubuntu-device-flash \- .SH SYNOPSIS -.B ubuntu-device-flash -[OPTIONS] - +\fBubuntu-device-flash\fP [OPTIONS] .SH DESCRIPTION -.B ubuntu-device-flash -Use this tool to flash a suported device with Ubuntu by either -bootstrapping from fastboot or reflashing from an already -supported device. .SH OPTIONS -\fB\-bootstrap\fR=\fIfalse\fR: Bootstrap the system, do this from fastboot -.HP -\fB\-channel=\fR"stable": Select channel to flash -.HP -\fB\-device=\fR"": Select device to flash -.HP -\fB\-list\-channels\fR=\fIfalse\fR: List available channels -.HP -\fB\-revision\fR=\fI0\fR: Revision to flash, 0 is current, use explicit version number or negative relative ones to current -.HP -\fB\-serial=\fR"": Serial of the device to operate -.HP -\fB\-server=\fR"https://system\-image.ubuntu.com": Select image server -.HP -\fB\-wipe\fR=\fIfalse\fR: Clear all data after flashing - -.SH EXAMPLES -To list the available channels on the server for the connected device -.PP -.nf -.RS -ubuntu-device-flash --list-channels -.RE -.fi -.PP - -To flash a full image over an existing Ubuntu Touch install with a different -channel -.PP -.nf -.RS -ubuntu-device-flash --channel [channel] -.RE -.fi -.PP - -To flash a full image over a non Ubuntu Touch install with the default -channel, do the following from fastboot -.PP -.nf -.RS -ubuntu-device-flash --bootstrap -.RE -.fi -.PP - -.SH ENVIRONMENT -.IP XDG_CACHE_HOME -If set, downloads take place in XDG_CACHE_HOME/ubuntuimages - -.SH AUTHOR -Sergio Schvezov +.TP +\fB--revision\fP +revision to use, absolute or relative allowed +.TP +\fB--download-only\fP +Only download. +.TP +\fB--server\fP +Use a different image server +.TP +\fB--clean-cache\fP +Cleans up cache with all downloaded bits +.TP +\fB--tls-skip-verify\fP +Skip TLS certificate validation +.TP +\fB-v, --verbose\fP +More messages will be printed out +.SH COMMANDS +.SS core +Creates ubuntu core images + +\fBUsage\fP: ubuntu-device-flash [OPTIONS] core [core-OPTIONS] + +.TP +\fB--channel\fP +Specify the channel to use +.TP +\fB--device\fP +Specify the device to use +.TP +\fB--keyboard-layout\fP +Specify the keyboard layout +.TP +\fB-o, --output\fP +Name of the image file to create +.TP +\fB-s, --size\fP +Size of image file to create in GB (min 4) +.TP +\fB--developer-mode\fP +Finds the latest public key in your ~/.ssh and sets it up using cloud-init +.TP +\fB--enable-ssh\fP +Enable ssh on the image through cloud-init(not needed with developer mode) +.TP +\fB--cloud\fP +Generate a pure cloud image without setting up cloud-init +.TP +\fB--platform\fP +specify the boards platform +.TP +\fB--install\fP +install additional packages (can be called multiple times) +.TP +\fB--device-part\fP +Specify a local device part to override the one from the server +.SS query +Run queries against the image server + +Choose from the list of query options to retrieve information from the server + +\fBUsage\fP: ubuntu-device-flash [OPTIONS] query [query-OPTIONS] + +.TP +\fB--list-channels\fP +List available channels +.TP +\fB--list-images\fP +List available images for a channel +.TP +\fB--show-image\fP +Show information for an image in the given channel +.TP +\fB--channel\fP +Specify an alternate channel +.TP +\fB--device\fP +Specify the device to use as a base for querying +.SS touch +Flashes ubuntu touch images + +\fBUsage\fP: ubuntu-device-flash [OPTIONS] touch [touch-OPTIONS] + +.TP +\fB--bootstrap\fP +bootstrap the system, do this from the bootloader +.TP +\fB--wipe\fP +Clear all data after flashing +.TP +\fB--serial\fP +Serial of the device to operate +.TP +\fB--developer-mode\fP +Enables developer mode after the factory reset, this is meant for automation and makes the device insecure by default (requires --password) +.TP +\fB--device-tarball\fP +Specify a local device tarball to override the one from the server (using official Ubuntu images with different device tarballs) +.TP +\fB--custom-tarball\fP +Specify a local custom tarball to override the one from the server (using official Ubuntu images with different custom tarballs) +.TP +\fB--run-script\fP +Run a script given by path to finish the flashing process, instead of rebooting to recovery (mostly used during development to work around quirky or incomplete recovery images) +.TP +\fB--password\fP +This sets up the default password for the phablet user. This option is meant for CI and not general use +.TP +\fB--channel\fP +Specify the channel to use +.TP +\fB--device\fP +Specify the device to flash +.TP +\fB--recovery-image\fP +Specify the recovery image file to use when flashing, overriding the one from the device tarball (useful if the latter has no adb enabled) diff -Nru goget-ubuntu-touch-0.12/diskimage/common.go goget-ubuntu-touch-0.16/diskimage/common.go --- goget-ubuntu-touch-0.12/diskimage/common.go 2015-01-16 02:05:53.000000000 +0000 +++ goget-ubuntu-touch-0.16/diskimage/common.go 2015-01-29 14:26:00.000000000 +0000 @@ -11,6 +11,7 @@ "fmt" "os" "os/exec" + "path/filepath" "strings" ) @@ -52,7 +53,7 @@ type CoreImage interface { Image SystemImage - SetupBoot() error + SetupBoot(OemDescription) error FlashExtra(string) error } @@ -64,6 +65,18 @@ Bootloader string `yaml:"bootloader"` } +type OemDescription struct { + Name string `yaml:"name"` + Version string `yaml:"version"` + Hardware struct { + Dtb string `yaml:"dtb,omitempty"` + } `yaml:"hardware,omitempty"` +} + +func (o OemDescription) InstallPath() string { + return filepath.Join("/oem", o.Name, o.Version) +} + func sectorSize(dev string) (string, error) { out, err := exec.Command("blockdev", "--getss", dev).CombinedOutput() if err != nil { diff -Nru goget-ubuntu-touch-0.12/diskimage/core_grub.go goget-ubuntu-touch-0.16/diskimage/core_grub.go --- goget-ubuntu-touch-0.12/diskimage/core_grub.go 2015-01-16 14:54:32.000000000 +0000 +++ goget-ubuntu-touch-0.16/diskimage/core_grub.go 2015-01-29 14:26:00.000000000 +0000 @@ -114,7 +114,7 @@ //Partition creates a partitioned image from an img func (img *CoreGrubImage) Partition() error { - if err := sysutils.CreateEmptyFile(img.location, img.size); err != nil { + if err := sysutils.CreateEmptyFile(img.location, img.size, sysutils.GB); err != nil { return err } @@ -247,6 +247,19 @@ return filepath.Join(img.baseMount, string(writableDir)) } +// Boot returns the system-boot path +func (img CoreGrubImage) Boot() string { + if img.parts == nil { + panic("img is not setup with partitions") + } + + if img.baseMount == "" { + panic("img not mounted") + } + + return filepath.Join(img.baseMount, string(bootDir)) +} + //System returns the system path func (img CoreGrubImage) System() string { if img.parts == nil { @@ -268,7 +281,7 @@ return img.baseMount } -func (img *CoreGrubImage) SetupBoot() error { +func (img *CoreGrubImage) SetupBoot(oem OemDescription) error { for _, dev := range []string{"dev", "proc", "sys"} { src := filepath.Join("/", dev) dst := filepath.Join(img.System(), dev) @@ -303,6 +316,30 @@ } defer unmount(rootDevPath) + efiDir := filepath.Join(img.System(), "boot", "efi") + if err := os.MkdirAll(efiDir, 0755); err != nil { + return fmt.Errorf("unable to create %s dir: %s", efiDir, err) + } + + if err := bindMount(img.Boot(), efiDir); err != nil { + return err + } + defer unmount(efiDir) + + // create efi layout + efiGrubDir := filepath.Join(img.System(), "boot", "efi", "EFI", "ubuntu", "grub") + if err := os.MkdirAll(efiGrubDir, 0755); err != nil { + return fmt.Errorf("unable to create %s dir: %s", efiGrubDir, err) + } + + bootGrubDir := filepath.Join(img.System(), "boot", "grub") + + if err := bindMount(efiGrubDir, bootGrubDir); err != nil { + return err + } + defer unmount(bootGrubDir) + + // install grub if out, err := exec.Command("chroot", img.System(), "grub-install", "/root_dev").CombinedOutput(); err != nil { return fmt.Errorf("unable to install grub: %s", out) } diff -Nru goget-ubuntu-touch-0.12/diskimage/core_uboot.go goget-ubuntu-touch-0.16/diskimage/core_uboot.go --- goget-ubuntu-touch-0.12/diskimage/core_uboot.go 2015-01-16 16:14:04.000000000 +0000 +++ goget-ubuntu-touch-0.16/diskimage/core_uboot.go 2015-01-29 14:26:00.000000000 +0000 @@ -55,7 +55,7 @@ loadinitrd=load mmc ${mmcdev}:${mmcpart} ${initrd_addr} ${snappy_ab}/${initrd_file}; setenv initrd_size ${filesize} loadfdt=load mmc ${mmcdev}:${mmcpart} ${fdtaddr} ${snappy_ab}/dtbs/${fdtfile} -# standard kernel and initrd file names; NB: ftdfile is set early from bootcmd +# standard kernel and initrd file names; NB: fdtfile is set early from bootcmd kernel_file=vmlinuz initrd_file=initrd.img {{ . }} @@ -72,7 +72,7 @@ snappy_mode=regular # if we're trying a new version, check if stamp file is already there to revert # to other version -snappy_boot=if test "${snappy_mode}" = "try"; then if load mmc ${bootpart} ${loadaddr} ${snappy_stamp} 0; then if test "${snappy_ab}" = "a"; then setenv snappy_ab "b"; else setenv snappy_ab "a"; fi; else fatwrite mmc ${mmcdev}:${mmcpart} 0x0 ${snappy_stamp} 0; fi; fi; run loadfiles; setenv mmcroot /dev/disk/by-label/system-${snappy_ab} ${snappy_cmdline}; run mmcargs; bootz ${loadaddr} ${initrd_addr}:${initrd_size} ${fdtaddr} +snappy_boot=if test "${snappy_mode}" = "try"; then if test -e mmc ${bootpart} ${snappy_stamp}; then if test "${snappy_ab}" = "a"; then setenv snappy_ab "b"; else setenv snappy_ab "a"; fi; else fatwrite mmc ${mmcdev}:${mmcpart} 0x0 ${snappy_stamp} 0; fi; fi; run loadfiles; setenv mmcroot /dev/disk/by-label/system-${snappy_ab} ${snappy_cmdline}; run mmcargs; bootz ${loadaddr} ${initrd_addr}:${initrd_size} ${fdtaddr} ` type FlashInstructions struct { @@ -138,7 +138,7 @@ //Partition creates a partitioned image from an img func (img *CoreUBootImage) Partition() error { - if err := sysutils.CreateEmptyFile(img.location, img.size); err != nil { + if err := sysutils.CreateEmptyFile(img.location, img.size, sysutils.GB); err != nil { return err } @@ -290,7 +290,7 @@ return img.baseMount } -func (img CoreUBootImage) SetupBoot() error { +func (img CoreUBootImage) SetupBoot(oem OemDescription) error { // destinations bootPath := filepath.Join(img.baseMount, string(bootDir)) bootAPath := filepath.Join(bootPath, "a") @@ -313,19 +313,19 @@ return err } - if err := move(hardwareYamlPath, filepath.Join(bootAPath, "hardware.yaml")); err != nil { + if err := copyFile(hardwareYamlPath, filepath.Join(bootAPath, "hardware.yaml")); err != nil { return err } - if err := move(kernelPath, filepath.Join(bootAPath, filepath.Base(kernelPath))); err != nil { + if err := copyFile(kernelPath, filepath.Join(bootAPath, filepath.Base(kernelPath))); err != nil { return err } - if err := move(initrdPath, filepath.Join(bootAPath, filepath.Base(initrdPath))); err != nil { + if err := copyFile(initrdPath, filepath.Join(bootAPath, filepath.Base(initrdPath))); err != nil { return err } - if err := img.provisionDtbs(bootDtbPath); err != nil { + if err := img.provisionDtbs(oem, bootDtbPath); err != nil { return err } @@ -344,13 +344,13 @@ } defer snappySystemFile.Close() - var ftdfile string + var fdtfile string if img.platform != "" { - ftdfile = fmt.Sprintf("ftdfile=%s.dtb", img.platform) + fdtfile = fmt.Sprintf("fdtfile=%s.dtb", img.platform) } t := template.Must(template.New("snappy-system").Parse(snappySystemTemplate)) - t.Execute(snappySystemFile, ftdfile) + t.Execute(snappySystemFile, fdtfile) return nil } @@ -374,7 +374,7 @@ // if a uEnv.txt is provided in the flashtool-assets, use it if _, err := os.Stat(uEnvPath); err == nil { printOut("Adding uEnv.txt to", bootuEnvPath) - if err := move(uEnvPath, bootuEnvPath); err != nil { + if err := copyFile(uEnvPath, bootuEnvPath); err != nil { return err } } else { @@ -384,7 +384,7 @@ return nil } -func (img CoreUBootImage) provisionDtbs(bootDtbPath string) error { +func (img CoreUBootImage) provisionDtbs(oem OemDescription, bootDtbPath string) error { dtbsPath := filepath.Join(img.baseMount, img.hardware.Dtbs) if _, err := os.Stat(dtbsPath); os.IsNotExist(err) { @@ -401,16 +401,23 @@ dtb := filepath.Join(dtbsPath, fmt.Sprintf("%s.dtb", img.platform)) // if there is a specific dtb for the platform, copy it. - if _, err := os.Stat(dtb); err == nil { + // First look in oem and then in device. + if oem.Hardware.Dtb != "" && img.platform != "" { + oemDtb := filepath.Join(img.System(), oem.InstallPath(), oem.Hardware.Dtb) dst := filepath.Join(bootDtbPath, filepath.Base(dtb)) - if err := move(dtb, dst); err != nil { + if err := copyFile(oemDtb, dst); err != nil { + return err + } + } else if _, err := os.Stat(dtb); err == nil { + dst := filepath.Join(bootDtbPath, filepath.Base(dtb)) + if err := copyFile(dtb, dst); err != nil { return err } } else { for _, dtbFi := range dtbFis { src := filepath.Join(dtbsPath, dtbFi.Name()) dst := filepath.Join(bootDtbPath, dtbFi.Name()) - if err := move(src, dst); err != nil { + if err := copyFile(src, dst); err != nil { return err } } @@ -475,7 +482,7 @@ return nil } -func move(src, dst string) error { +func copyFile(src, dst string) error { dstFile, err := os.Create(dst) if err != nil { return err @@ -486,7 +493,6 @@ if err != nil { return err } - defer os.Remove(src) defer srcFile.Close() reader := bufio.NewReader(srcFile) diff -Nru goget-ubuntu-touch-0.12/diskimage/image.go goget-ubuntu-touch-0.16/diskimage/image.go --- goget-ubuntu-touch-0.12/diskimage/image.go 2015-01-12 20:12:00.000000000 +0000 +++ goget-ubuntu-touch-0.16/diskimage/image.go 2015-01-28 22:44:25.000000000 +0000 @@ -155,7 +155,7 @@ panic("creating ext4 on images with multiple parts not supported") } - if err := sysutils.CreateEmptyFile(img.path, img.size); err != nil { + if err := sysutils.CreateEmptyFile(img.path, img.size, sysutils.GiB); err != nil { return err } @@ -164,7 +164,7 @@ //CreateVFat returns a vfat partition for a given file func (img DiskImage) CreateVFat() error { - if err := sysutils.CreateEmptyFile(img.path, img.size); err != nil { + if err := sysutils.CreateEmptyFile(img.path, img.size, sysutils.GiB); err != nil { return err } return exec.Command("mkfs.vfat", "-n", img.label, img.path).Run() diff -Nru goget-ubuntu-touch-0.12/sysutils/utils.go goget-ubuntu-touch-0.16/sysutils/utils.go --- goget-ubuntu-touch-0.12/sysutils/utils.go 2015-01-16 16:14:04.000000000 +0000 +++ goget-ubuntu-touch-0.16/sysutils/utils.go 2015-01-28 22:44:25.000000000 +0000 @@ -27,7 +27,14 @@ "syscall" ) -func CreateEmptyFile(path string, size int64) (err error) { +type unit int64 + +const ( + GiB unit = 1024 + GB unit = 1000 +) + +func CreateEmptyFile(path string, size int64, u unit) (err error) { file, err := os.Create(path) if err != nil { return err @@ -38,7 +45,16 @@ os.Remove(path) } }() - size = size * 1000 * 1000 * 1000 + + switch u { + case GiB: + size = size * 1024 * 1024 * 1024 + case GB: + size = size * 1000 * 1000 * 1000 + default: + panic("improper sizing unit used") + } + if err := file.Truncate(size); err != nil { return errors.New(fmt.Sprintf("Error creating %s of size %d to stage image onto", path, size)) } diff -Nru goget-ubuntu-touch-0.12/ubuntu-device-flash/core.go goget-ubuntu-touch-0.16/ubuntu-device-flash/core.go --- goget-ubuntu-touch-0.12/ubuntu-device-flash/core.go 2015-01-16 16:14:04.000000000 +0000 +++ goget-ubuntu-touch-0.16/ubuntu-device-flash/core.go 2015-01-29 14:26:00.000000000 +0000 @@ -55,7 +55,7 @@ Output string `long:"output" short:"o" description:"Name of the image file to create" required:"true"` Size int64 `long:"size" short:"s" description:"Size of image file to create in GB (min 4)" default:"20"` DeveloperMode bool `long:"developer-mode" description:"Finds the latest public key in your ~/.ssh and sets it up using cloud-init"` - EnableSsh bool `long:"enable-ssh" description:"Enable ssh on the image through cloud-init(not need with developer mode)"` + EnableSsh bool `long:"enable-ssh" description:"Enable ssh on the image through cloud-init(not needed with developer mode)"` Cloud bool `long:"cloud" description:"Generate a pure cloud image without setting up cloud-init"` Platform string `long:"platform" description:"specify the boards platform"` Install []string `long:"install" description:"install additional packages (can be called multiple times)"` @@ -76,6 +76,7 @@ password: ubuntu chpasswd: { expire: False } ssh_pwauth: True +ssh_genkeytypes: ['rsa', 'dsa', 'ecdsa', 'ed25519'] ` func (coreCmd *CoreCmd) Execute(args []string) error { @@ -318,15 +319,21 @@ systemPath := img.System() - if err := img.SetupBoot(); err != nil { + if err := coreCmd.install(systemPath); err != nil { return err } - if err := coreCmd.setupKeyboardLayout(systemPath); err != nil { + // check if we installed an oem snap + oem, err := loadOem(systemPath) + if err != nil { return err } - if err := coreCmd.install(systemPath); err != nil { + if err := img.SetupBoot(oem); err != nil { + return err + } + + if err := coreCmd.setupKeyboardLayout(systemPath); err != nil { return err } @@ -493,6 +500,31 @@ return string(pubKey), err } +func loadOem(systemPath string) (oem diskimage.OemDescription, err error) { + pkgs, err := filepath.Glob(filepath.Join(systemPath, "/oem/*/*/meta/package.yaml")) + if err != nil { + return oem, err + } + + // checking for len(pkgs) > 2 due to the 'current' symlink + if len(pkgs) == 0 { + return oem, nil + } else if len(pkgs) > 2 || err != nil { + return oem, errors.New("too many oem packages installed") + } + + f, err := ioutil.ReadFile(pkgs[0]) + if err != nil { + return oem, errors.New("failed to read oem yaml") + } + + if err := goyaml.Unmarshal([]byte(f), &oem); err != nil { + return oem, errors.New("cannot decode oem yaml") + } + + return oem, nil +} + func extractHWDescription(path string) (hw diskimage.HardwareDescription, err error) { // hack to circumvent https://code.google.com/p/go/issues/detail?id=1435 if syscall.Getuid() == 0 { diff -Nru goget-ubuntu-touch-0.12/ubuntu-device-flash/main.go goget-ubuntu-touch-0.16/ubuntu-device-flash/main.go --- goget-ubuntu-touch-0.12/ubuntu-device-flash/main.go 2014-12-06 01:18:19.000000000 +0000 +++ goget-ubuntu-touch-0.16/ubuntu-device-flash/main.go 2015-01-28 22:44:25.000000000 +0000 @@ -45,6 +45,20 @@ func main() { args := os.Args + if v := os.Getenv("MANPAGE"); v != "" { + manpagePath := "/tmp/ubuntu-device-flash.manpage" + w, err := os.Create(manpagePath) + if err != nil { + fmt.Println(err) + return + } + + parser.WriteManPage(w) + fmt.Println("Created manpage at", manpagePath) + + return + } + if _, err := parser.ParseArgs(args); err != nil && parser.Active == nil { if e, ok := err.(*flags.Error); ok { if e.Type == flags.ErrHelp {