diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/.bzr-builddeb/default.conf goget-ubuntu-touch-0.34+16.10.20160805/.bzr-builddeb/default.conf --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/.bzr-builddeb/default.conf 1970-01-01 00:00:00.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/.bzr-builddeb/default.conf 2016-08-09 09:01:48.000000000 +0000 @@ -0,0 +1,2 @@ +[BUILDDEB] +split = True diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/debian/bzr-builder.manifest goget-ubuntu-touch-0.34+16.10.20160805/debian/bzr-builder.manifest --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/debian/bzr-builder.manifest 1970-01-01 00:00:00.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/debian/bzr-builder.manifest 2016-08-09 09:01:48.000000000 +0000 @@ -0,0 +1,2 @@ +# bzr-builder format 0.3 deb-version {debupstream}-0~233 +lp:goget-ubuntu-touch revid:ci-train-bot@canonical.com-20160805132110-28gg9dbcuipfvrt1 diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/debian/changelog goget-ubuntu-touch-0.34+16.10.20160805/debian/changelog --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/debian/changelog 2016-09-07 11:22:14.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/debian/changelog 2016-08-09 09:01:48.000000000 +0000 @@ -1,8 +1,44 @@ -goget-ubuntu-touch (0.33-0ubuntu1~xenial-staging) xenial; urgency=medium +goget-ubuntu-touch (0.34+16.10.20160805-0~233~ubuntu16.04.1) xenial; urgency=low - * Intermmediate release. + * Auto build. - -- Sergio Schvezov Fri, 01 Apr 2016 07:34:26 -0300 + -- Zoltan Balogh Tue, 09 Aug 2016 09:01:48 +0000 + +goget-ubuntu-touch (0.34+16.10.20160805-0ubuntu1) yakkety; urgency=medium + + [ Andrea Bernabei ] + * Default to ubuntu-touch/stable instead of ubuntu-touch/devel for + emulator creation (LP: #1594306) + + -- Łukasz Zemczak Fri, 05 Aug 2016 13:21:10 +0000 + +goget-ubuntu-touch (0.34+16.10.20160722-0ubuntu1) yakkety; urgency=medium + + [ Simon Fels ] + * Add bootstrap support for turbo/frieza/cooler devices + + -- Łukasz Zemczak Fri, 22 Jul 2016 16:02:30 +0000 + +goget-ubuntu-touch (0.34-0ubuntu1) xenial; urgency=medium + + [ Ondrej Kubik ] + * touch: new adb support with key support. by w-ondra approved by mvo + LP: #1316302 + + -- Michael Vogt Tue, 05 Apr 2016 12:21:07 +0200 + +goget-ubuntu-touch (0.33-0ubuntu3) xenial; urgency=medium + + * remove support for building ubuntu-core (snappy) images + until the kernel/gadget snap specification is finalized + + -- Michael Vogt Tue, 05 Apr 2016 09:46:47 +0200 + +goget-ubuntu-touch (0.33-0ubuntu2) xenial; urgency=medium + + * debian/control: Remove version Build-Depends for golang-snappy-dev. + + -- Sergio Schvezov Wed, 18 Nov 2015 09:32:39 -0300 goget-ubuntu-touch (0.33-0ubuntu1) xenial; urgency=medium diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/debian/control goget-ubuntu-touch-0.34+16.10.20160805/debian/control --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/debian/control 2016-09-07 11:22:14.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/debian/control 2016-08-09 09:01:48.000000000 +0000 @@ -6,17 +6,12 @@ dh-golang, bash-completion, golang-go, - golang-ar-dev, golang-gettext-dev, golang-go-flags-dev, golang-gocheck-dev, - golang-github-mvo5-goconfigparser-dev, golang-juju-loggo-dev, golang-pb-dev, - golang-github-ubuntu-core-snappy-dev, - golang-github-mvo5-uboot-go-dev, golang-yaml.v2-dev, - ubuntu-snappy-cli, Standards-Version: 3.9.5 Homepage: https://launchpad.net/goget-ubuntu-touch Vcs-Browser: http://bazaar.launchpad.net/~phablet-team/goget-ubuntu-touch/trunk/files @@ -33,7 +28,6 @@ kpartx, parted, qemu-user-static, - ubuntu-snappy-cli, ${misc:Depends}, ${shlibs:Depends}, Built-Using: ${misc:Built-Using} diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/dependencies.tsv goget-ubuntu-touch-0.34+16.10.20160805/dependencies.tsv --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/dependencies.tsv 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/dependencies.tsv 2016-08-09 09:01:48.000000000 +0000 @@ -1,8 +1,6 @@ +github.com/blakesmith/ar git 8bd4349a67f2533b078dbc524689d15dba0f4659 2015-03-11T14:59:44Z github.com/cheggaaa/pb git da1f27ad1d9509b16f65f52fd9d8138b0f2dc7b2 2015-08-13T11:06:09Z github.com/gosexy/gettext git 98b7b91596d20b96909e6b60d57411547dd9959c 2013-02-21T11:21:43Z github.com/jessevdk/go-flags git 4047bd797dd935ae2b557a79cc43f223066c9659 2015-10-18T21:15:10Z -github.com/mvo5/goconfigparser git 26426272dda20cc76aa1fa44286dc743d2972fe8 2015-02-12T09:37:50Z -github.com/mvo5/uboot-go git 69978a3e4b05cca9d7cfee489b3453dfed45e72c 2015-07-23T08:17:10Z -github.com/ubuntu-core/snappy git a6e683cb4eca7027b331713c2f10e26a31050f20 2016-01-14T16:39:06Z gopkg.in/yaml.v2 git 7ad95dd0798a40da1ccdff6dff35fd177b5edf40 2015-06-24T10:29:02Z launchpad.net/gocheck bzr gustavo@niemeyer.net-20140225173054-xu9zlkf9kxhvow02 87 diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/devices/fastboot.go goget-ubuntu-touch-0.34+16.10.20160805/devices/fastboot.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/devices/fastboot.go 2016-03-29 15:39:25.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/devices/fastboot.go 2016-08-09 09:01:48.000000000 +0000 @@ -85,3 +85,10 @@ } return device, err } + +// Send OEM specific commands to bootloader +func (fastboot Fastboot) SendOemCommand(command string) (err error) { + cmd := append(fastboot.params, []string{"oem", command}...) + err = exec.Command(fastbootCommand, cmd...).Run() + return err +} diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/bootloader.go goget-ubuntu-touch-0.34+16.10.20160805/diskimage/bootloader.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/bootloader.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/diskimage/bootloader.go 2016-08-09 09:01:48.000000000 +0000 @@ -89,27 +89,21 @@ printOut("Setting up raw boot asset partitions for", imagePath, "...") var part int = partCount - pos := 0 for _, asset := range rawPartitions { part += 1 - printOut("creating partition:", asset.Name) - // override position if specified, otherwise use the - // previous position - if asset.Pos > 0 { - pos = asset.Pos + size, err := strconv.Atoi(asset.Size) + if err != nil { + return err } + size = size * 2 - // why * 2? - size := asset.Size * 2 + printOut("creating partition:", asset.Name) - opts := fmt.Sprintf("%d:%d:+%d", part, pos, size) - if output, err := exec.Command("sgdisk", "-a", "1", "-n", opts, imagePath).CombinedOutput(); err != nil { - println(string(output)) + opts := fmt.Sprintf("0:0:+%d", size) + if err := exec.Command("sgdisk", "-a", "1", "-n", opts, imagePath).Run(); err != nil { return err } - // move postition forward - pos += size opts = fmt.Sprintf("%d:%s", part, asset.Name) if err := exec.Command("sgdisk", "-c", opts, imagePath).Run(); err != nil { @@ -120,9 +114,10 @@ if err := exec.Command("sgdisk", "-t", opts, imagePath).Run(); err != nil { return err } + } - printOut("aligning partitions") + printOut("sorting partitions") if err := exec.Command("sgdisk", "-s", imagePath).Run(); err != nil { return err } diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/common.go goget-ubuntu-touch-0.34+16.10.20160805/diskimage/common.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/common.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/diskimage/common.go 2016-08-09 09:01:48.000000000 +0000 @@ -17,6 +17,8 @@ "path/filepath" "strings" "syscall" + + "launchpad.net/goget-ubuntu-touch/sysutils" ) // This program is free software: you can redistribute it and/or modify it @@ -45,6 +47,10 @@ initrdFileName = "initrd.img" ) +const ( + partLayoutSystemAB = "system-AB" +) + var ( syscallSync = syscall.Sync ) @@ -83,8 +89,7 @@ type BootAssetRawPartitions struct { Name string `yaml:"name"` - Size int `yaml:"size"` - Pos int `yaml:"pos"` + Size string `yaml:"size"` Type string `yaml:"type"` } @@ -102,11 +107,11 @@ RawPartitions []BootAssetRawPartitions `yaml:"raw-partitions,omitempty"` } -type GadgetDescription struct { +type OemDescription struct { Name string `yaml:"name"` Version string `yaml:"version"` - Gadget struct { + OEM struct { Hardware struct { Bootloader string `yaml:"bootloader"` PartitionLayout string `yaml:"partition-layout"` @@ -124,7 +129,7 @@ Store *struct { ID string `yaml:"id,omitempty"` } - } `yaml:"gadget,omitempty"` + } `yaml:"oem,omitempty"` Config struct { UbuntuCore struct { @@ -135,52 +140,53 @@ rootDir string } -func (o *GadgetDescription) SetRoot(rootDir string) { +func (o *OemDescription) SetRoot(rootDir string) { o.rootDir = rootDir } // SystemParts returns the system labels depending on the partition layout. // // The default is to return a flat structure for any unknown layout. -func (o *GadgetDescription) SystemParts() []string { - switch o.Gadget.Hardware.PartitionLayout { +func (o *OemDescription) SystemParts() []string { + switch o.OEM.Hardware.PartitionLayout { + case partLayoutSystemAB: + return []string{"a", "b"} default: return []string{""} } } -func (o GadgetDescription) InstallPath() (string, error) { - - glob, err := filepath.Glob(fmt.Sprintf("%s/gadget/*/*", o.rootDir)) +func (o OemDescription) InstallPath() (string, error) { + glob, err := filepath.Glob(fmt.Sprintf("%s/oem/%s/current", o.rootDir, o.Name)) if err != nil { return "", err } if len(glob) != 1 { - return "", errors.New("gadget package not installed") + return "", errors.New("oem package not installed") } return glob[0], nil } -func (o GadgetDescription) Architecture() string { - return o.Gadget.Hardware.Architecture +func (o OemDescription) Architecture() string { + return o.OEM.Hardware.Architecture } -func (o *GadgetDescription) SetArchitecture(architecture string) { - o.Gadget.Hardware.Architecture = architecture +func (o *OemDescription) SetArchitecture(architecture string) { + o.OEM.Hardware.Architecture = architecture } -func (o GadgetDescription) PartitionLayout() string { - return o.Gadget.Hardware.PartitionLayout +func (o OemDescription) PartitionLayout() string { + return o.OEM.Hardware.PartitionLayout } -func (o GadgetDescription) Platform() string { - return o.Gadget.Hardware.Platform +func (o OemDescription) Platform() string { + return o.OEM.Hardware.Platform } -func (o *GadgetDescription) SetPlatform(platform string) { - o.Gadget.Hardware.Platform = platform +func (o *OemDescription) SetPlatform(platform string) { + o.OEM.Hardware.Platform = platform } func sectorSize(dev string) (string, error) { @@ -194,20 +200,17 @@ // BaseImage implements the basic primitives to manage images. type BaseImage struct { - baseMount string - bindMounts []string - hardware HardwareDescription - location string - gadget GadgetDescription - parts []partition - partCount int - size int64 - rootSize int - label string + baseMount string + hardware HardwareDescription + location string + oem OemDescription + parts []partition + partCount int + size int64 + rootSize int + label string } -var bindMounts = []string{"dev", "sys", "proc", filepath.Join("sys", "firmware")} - // Mount mounts the image. This also maps the loop device. func (img *BaseImage) Mount() error { if err := img.doMap(); err != nil { @@ -264,27 +267,8 @@ } img.baseMount = baseMount - mountpoints := make([]string, 0, len(bindMounts)) - if img.gadget.PartitionLayout() == "minimal" { - mountpoints = bindMounts - - for _, d := range mountpoints { - p := filepath.Join(baseMount, d) - - if err := os.MkdirAll(p, 0755); err != nil { - return err - } - - printOut("Bind mounting", d, "to", p) - if err := bindMount(filepath.Join("/", d), p); err != nil { - return err - } - - img.bindMounts = append(img.bindMounts, p) - } - } - return nil + } // Unmount unmounts the image. This also unmaps the loop device. @@ -299,13 +283,6 @@ panic("No base mountpoint set") } - for i := len(img.bindMounts) - 1; i >= 0; i-- { - if err := unmount(img.bindMounts[i]); err != nil { - return err - } - } - img.bindMounts = nil - syscallSync() for _, part := range img.parts { @@ -489,28 +466,55 @@ } func (img *BaseImage) GenericBootSetup(bootPath string) error { - gadgetRoot, err := img.gadget.InstallPath() + // origins + hardwareYamlPath := filepath.Join(img.baseMount, hardwareFileName) + kernelPath := filepath.Join(img.baseMount, img.hardware.Kernel) + initrdPath := filepath.Join(img.baseMount, img.hardware.Initrd) + + // populate both A/B + for _, part := range img.oem.SystemParts() { + path := filepath.Join(bootPath, part) + + printOut("Setting up", path) + + if err := os.MkdirAll(path, 0755); err != nil { + return err + } + + if err := sysutils.CopyFile(hardwareYamlPath, filepath.Join(path, hardwareFileName)); err != nil { + return err + } + + if err := sysutils.CopyFile(kernelPath, filepath.Join(path, kernelFileName)); err != nil { + return err + } + + if err := sysutils.CopyFile(initrdPath, filepath.Join(path, initrdFileName)); err != nil { + return err + } + } + + oemRoot, err := img.oem.InstallPath() if err != nil { return err } - return setupBootAssetFiles(img.Boot(), bootPath, gadgetRoot, img.gadget.Gadget.Hardware.BootAssets.Files) + return setupBootAssetFiles(img.Boot(), bootPath, oemRoot, img.oem.OEM.Hardware.BootAssets.Files) } func (img *BaseImage) FlashExtra() error { - gadgetRoot, err := img.gadget.InstallPath() + oemRoot, err := img.oem.InstallPath() if err != nil { return err } - if bootAssets := img.gadget.Gadget.Hardware.BootAssets; bootAssets != nil { + if bootAssets := img.oem.OEM.Hardware.BootAssets; bootAssets != nil { if bootAssets.RawPartitions != nil { if err := setupBootAssetRawPartitions(img.location, img.partCount, bootAssets.RawPartitions); err != nil { return err } } - - return setupBootAssetRawFiles(img.location, gadgetRoot, bootAssets.RawFiles) + return setupBootAssetRawFiles(img.location, oemRoot, bootAssets.RawFiles) } return nil @@ -521,19 +525,3 @@ fmt.Println(args...) } } - -func bindMount(src, dst string) error { - if out, err := exec.Command("mount", "--bind", src, dst).CombinedOutput(); err != nil { - return fmt.Errorf("issues while bind mounting: %s", out) - } - - return nil -} - -func unmount(dst string) error { - if out, err := exec.Command("umount", dst).CombinedOutput(); err != nil { - return fmt.Errorf("issues while unmounting: %s", out) - } - - return nil -} diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/common_test.go goget-ubuntu-touch-0.34+16.10.20160805/diskimage/common_test.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/common_test.go 2016-04-01 10:12:22.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/diskimage/common_test.go 2016-08-09 09:01:48.000000000 +0000 @@ -28,7 +28,7 @@ type CommonTestSuite struct { tmpdir string - gadget GadgetDescription + oem OemDescription packageInst string } @@ -36,27 +36,27 @@ func (s *CommonTestSuite) SetUpTest(c *C) { s.tmpdir = c.MkDir() - s.gadget = GadgetDescription{Name: "packagename", Version: "42"} - s.packageInst = s.gadget.Name + s.oem = OemDescription{Name: "packagename", Version: "42"} + s.packageInst = s.oem.Name } func (s *CommonTestSuite) TestOemInstallPath(c *C) { - err := os.MkdirAll(filepath.Join(s.tmpdir, "gadget", s.packageInst, "current"), 0755) + err := os.MkdirAll(filepath.Join(s.tmpdir, "oem", s.packageInst, "current"), 0755) c.Assert(err, IsNil) - s.gadget.SetRoot(s.tmpdir) - installPath, err := s.gadget.InstallPath() + s.oem.SetRoot(s.tmpdir) + installPath, err := s.oem.InstallPath() c.Assert(err, IsNil) - c.Assert(installPath, Equals, filepath.Join(s.tmpdir, "gadget/packagename/current")) + c.Assert(installPath, Equals, filepath.Join(s.tmpdir, "oem/packagename/current")) } func (s *CommonTestSuite) TestOemInstallPathNoOem(c *C) { - err := os.MkdirAll(filepath.Join(s.tmpdir, "gadget", s.packageInst), 0755) + err := os.MkdirAll(filepath.Join(s.tmpdir, "oem", s.packageInst), 0755) c.Assert(err, IsNil) - s.gadget.SetRoot(s.tmpdir) - installPath, err := s.gadget.InstallPath() + s.oem.SetRoot(s.tmpdir) + installPath, err := s.oem.InstallPath() c.Assert(err, NotNil) c.Assert(installPath, Equals, "") diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/core_grub.go goget-ubuntu-touch-0.34+16.10.20160805/diskimage/core_grub.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/core_grub.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/diskimage/core_grub.go 2016-08-09 09:01:48.000000000 +0000 @@ -5,7 +5,6 @@ // // Written by Sergio Schvezov // - package diskimage import ( @@ -32,34 +31,25 @@ // You should have received a copy of the GNU General Public License along // with this program. If not, see . -// CoreGrubImage holds the logic to create a core image using grub. type CoreGrubImage struct { BaseImage legacyGrub bool } -// NewCoreGrubImage creates a new instance of CoreGrubImage -func NewCoreGrubImage(location string, size int64, rootSize int, hw HardwareDescription, gadget GadgetDescription, updateGrub bool, label string) *CoreGrubImage { - var partCount int - switch gadget.PartitionLayout() { - case "minimal": - partCount = 3 - } - +func NewCoreGrubImage(location string, size int64, rootSize int, hw HardwareDescription, oem OemDescription, updateGrub bool, label string) *CoreGrubImage { return &CoreGrubImage{ BaseImage: BaseImage{ location: location, size: size, rootSize: rootSize, hardware: hw, - gadget: gadget, - partCount: partCount, + oem: oem, + partCount: 5, label: label, }, legacyGrub: updateGrub, } - } const grubCfgContent = `# console only, no graphics/vga @@ -85,10 +75,9 @@ } parted.addPart(grubLabel, "", fsNone, 4) - switch img.gadget.PartitionLayout() { - case "minimal": - parted.addPart(bootLabel, bootDir, fsFat32, 64) - } + parted.addPart(bootLabel, bootDir, fsFat32, 128) + parted.addPart(systemALabel, systemADir, fsExt4, img.rootSize) + parted.addPart(systemBLabel, systemBDir, fsExt4, img.rootSize) parted.addPart(writableLabel, writableDir, fsExt4, -1) parted.setBoot(2) @@ -99,7 +88,6 @@ return parted.create(img.location) } -// SetupBoot sets up the bootloader logic for the image. func (img *CoreGrubImage) SetupBoot() error { if !img.legacyGrub { // destinations @@ -133,14 +121,14 @@ return errors.New("cannot determined absolute path for output image") } - rootDevPath := filepath.Join(img.System(), "tmp", "root_dev") + rootDevPath := filepath.Join(img.System(), "root_dev") - f, err := os.Create(rootDevPath) - if err != nil { + if f, err := os.Create(rootDevPath); err != nil { return err + } else { + f.Close() + defer os.Remove(rootDevPath) } - f.Close() - defer os.Remove(rootDevPath) if err := bindMount(outputPath, rootDevPath); err != nil { return err @@ -177,7 +165,7 @@ var grubTarget string - arch := img.gadget.Architecture() + arch := img.oem.Architecture() switch arch { case "armhf": @@ -186,15 +174,13 @@ grubTarget = "x86_64-efi" case "i386": grubTarget = "i386-efi" - case "arm64": - grubTarget = "arm64-efi" default: return fmt.Errorf("unsupported architecture for GRUB on EFI: %s", arch) } if arch == "amd64" || arch == "i386" { // install grub BIOS support - if out, err := exec.Command("chroot", img.System(), "grub-install", "tmp/root_dev").CombinedOutput(); err != nil { + if out, err := exec.Command("chroot", img.System(), "grub-install", "/root_dev").CombinedOutput(); err != nil { return fmt.Errorf("unable to install grub (BIOS): %s", out) } } @@ -246,4 +232,20 @@ } return nil +} + +func bindMount(src, dst string) error { + if out, err := exec.Command("mount", "--bind", src, dst).CombinedOutput(); err != nil { + return fmt.Errorf("issues while bind mounting: %s", out) + } + + return nil +} + +func unmount(dst string) error { + if out, err := exec.Command("umount", dst).CombinedOutput(); err != nil { + return fmt.Errorf("issues while unmounting: %s", out) + } + + return nil } diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/core_uboot.go goget-ubuntu-touch-0.34+16.10.20160805/diskimage/core_uboot.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/core_uboot.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/diskimage/core_uboot.go 2016-08-09 09:01:48.000000000 +0000 @@ -66,21 +66,15 @@ Bootloader []string `yaml:"bootloader"` } -func NewCoreUBootImage(location string, size int64, rootSize int, hw HardwareDescription, gadget GadgetDescription, label string) *CoreUBootImage { - var partCount int - switch gadget.PartitionLayout() { - case "minimal": - partCount = 2 - } - +func NewCoreUBootImage(location string, size int64, rootSize int, hw HardwareDescription, oem OemDescription, label string) *CoreUBootImage { return &CoreUBootImage{ BaseImage{ hardware: hw, - gadget: gadget, + oem: oem, location: location, size: size, rootSize: rootSize, - partCount: partCount, + partCount: 4, label: label, }, } @@ -101,10 +95,9 @@ return err } - switch img.gadget.PartitionLayout() { - case "minimal": - parted.addPart(bootLabel, bootDir, fsFat32, 128) - } + parted.addPart(bootLabel, bootDir, fsFat32, 128) + parted.addPart(systemALabel, systemADir, fsExt4, 1024) + parted.addPart(systemBLabel, systemBDir, fsExt4, 1024) parted.addPart(writableLabel, writableDir, fsExt4, -1) parted.setBoot(1) @@ -124,7 +117,7 @@ } // populate both A/B - for _, part := range img.gadget.SystemParts() { + for _, part := range img.oem.SystemParts() { bootDtbPath := filepath.Join(bootPath, part, "dtbs") if err := img.provisionDtbs(bootDtbPath); err != nil { return err @@ -138,7 +131,7 @@ defer snappySystemFile.Close() var fdtfile string - if platform := img.gadget.Platform(); platform != "" { + if platform := img.oem.Platform(); platform != "" { fdtfile = fmt.Sprintf("fdtfile=%s.dtb", platform) } @@ -161,32 +154,28 @@ return err } - var dtbFis []os.FileInfo - if img.hardware.Dtbs != "" { - var err error - dtbFis, err = ioutil.ReadDir(dtbsPath) - if err != nil { - return err - } + dtbFis, err := ioutil.ReadDir(dtbsPath) + if err != nil { + return err } if err := os.MkdirAll(bootDtbPath, 0755); err != nil { return err } - dtb := filepath.Join(dtbsPath, fmt.Sprintf("%s.dtb", img.gadget.Platform())) + dtb := filepath.Join(dtbsPath, fmt.Sprintf("%s.dtb", img.oem.Platform())) // if there is a specific dtb for the platform, copy it. - // First look in gadget and then in device. - if gadgetDtb := img.gadget.Gadget.Hardware.Dtb; gadgetDtb != "" && img.gadget.Platform() != "" { - gadgetRoot, err := img.gadget.InstallPath() + // First look in oem and then in device. + if oemDtb := img.oem.OEM.Hardware.Dtb; oemDtb != "" && img.oem.Platform() != "" { + oemRoot, err := img.oem.InstallPath() if err != nil { return err } - gadgetDtb := filepath.Join(gadgetRoot, gadgetDtb) + oemDtb := filepath.Join(oemRoot, oemDtb) dst := filepath.Join(bootDtbPath, filepath.Base(dtb)) - if err := sysutils.CopyFile(gadgetDtb, dst); err != nil { + if err := sysutils.CopyFile(oemDtb, dst); err != nil { return err } } else if _, err := os.Stat(dtb); err == nil { diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/partition.go goget-ubuntu-touch-0.34+16.10.20160805/diskimage/partition.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/diskimage/partition.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/diskimage/partition.go 2016-08-09 09:01:48.000000000 +0000 @@ -5,7 +5,6 @@ // // Written by Sergio Schvezov // - package diskimage import ( diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/common.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/common.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/common.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/common.go 2016-08-09 09:01:48.000000000 +0000 @@ -61,11 +61,11 @@ // expandFile checks for file existence, correct permissions and returns the absolute path. func expandFile(path string) (abspath string, err error) { - p, err := filepath.Abs(path) - if err != nil { + if p, err := filepath.Abs(path); err != nil { return "", err + } else { + abspath = p } - abspath = p fi, err := os.Lstat(abspath) if err != nil { diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/core.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/core.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/core.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/core.go 2016-08-09 09:01:48.000000000 +0000 @@ -77,20 +77,21 @@ if !coreCmd.Deprecated.Cloud { coreCmd.customizationFunc = append(coreCmd.customizationFunc, coreCmd.setupCloudInit) - coreCmd.customizationFunc = append(coreCmd.customizationFunc, coreCmd.setupGadgetConfigs) + coreCmd.customizationFunc = append(coreCmd.customizationFunc, coreCmd.setupOemConfigs) } return coreCmd.create() } // this is a hackish way to get the config in place -func (coreCmd *CoreCmd) setupGadgetConfigs() error { - modprobeDContent := coreCmd.gadget.Config.UbuntuCore.Modprobe +func (coreCmd *CoreCmd) setupOemConfigs() error { + modprobeDContent := coreCmd.oem.Config.UbuntuCore.Modprobe if modprobeDContent == nil { + printOut("no modprobe") return nil } - fmt.Println("Setting up gadget hooks...") + fmt.Println("Setting up oem hooks...") writablePath := coreCmd.img.Writable() @@ -100,11 +101,12 @@ } // first we need to copy all the files in modprobe.d - systemModprobeDir := filepath.Join(coreCmd.img.System(), "etc", "modprobe.d") - // FIXME: can we do "cp -a" here? - if err := RSyncWithDelete(systemModprobeDir, modprobeDir); err != nil { - return err - } + /* + systemModprobeDir := filepath.Join(coreCmd.img.System(), "etc", "modprobe.d") + if err := helpers.RSyncWithDelete(systemModprobeDir, modprobeDir); err != nil { + return err + } + */ modprobeD := filepath.Join(modprobeDir, "ubuntu-core.conf") modprobeDFile, err := os.Create(modprobeD) diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/helpers.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/helpers.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/helpers.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/helpers.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,89 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2014-2015 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "syscall" - - "github.com/ubuntu-core/snappy/osutil" -) - -// RSyncWithDelete syncs srcDir to destDir -func RSyncWithDelete(srcDirName, destDirName string) error { - // first remove everything thats not in srcdir - err := filepath.Walk(destDirName, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - // relative to the root "destDirName" - relPath := path[len(destDirName):] - if !osutil.FileExists(filepath.Join(srcDirName, relPath)) { - if err := os.RemoveAll(path); err != nil { - return err - } - if info.IsDir() { - return filepath.SkipDir - } - } - return nil - }) - if err != nil { - return err - } - - // then copy or update the data from srcdir to destdir - err = filepath.Walk(srcDirName, func(src string, info os.FileInfo, err error) error { - if err != nil { - return err - } - - // relative to the root "srcDirName" - relPath := src[len(srcDirName):] - dst := filepath.Join(destDirName, relPath) - if info.IsDir() { - if err := os.MkdirAll(dst, info.Mode()); err != nil { - return err - } - - // this can panic. The alternative would be to use the "st, ok" pattern, and then if !ok... panic? - st := info.Sys().(*syscall.Stat_t) - ts := []syscall.Timespec{st.Atim, st.Mtim} - - return syscall.UtimesNano(dst, ts) - } - if !osutil.FilesAreEqual(src, dst) { - // XXX: we should (eventually) use CopyFile here, - // but we need to teach it about preserving - // of atime/mtime and permissions - output, err := exec.Command("cp", "-va", src, dst).CombinedOutput() - if err != nil { - return fmt.Errorf("Failed to copy %s to %s (%s)", src, dst, output) - } - } - return nil - }) - - return err -} diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/helpers_test.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/helpers_test.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/helpers_test.go 2016-04-01 10:09:12.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/helpers_test.go 1970-01-01 00:00:00.000000000 +0000 @@ -1,135 +0,0 @@ -// -*- Mode: Go; indent-tabs-mode: t -*- - -/* - * Copyright (C) 2014-2015 Canonical Ltd - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 3 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package main - -import ( - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - - . "launchpad.net/gocheck" -) - -type HTestSuite struct{} - -var _ = Suite(&HTestSuite{}) - -func makeTestFiles(c *C, srcDir, destDir string) { - // a new file - err := ioutil.WriteFile(filepath.Join(srcDir, "new"), []byte(nil), 0644) - c.Assert(err, IsNil) - - // a existing file that needs update - err = ioutil.WriteFile(filepath.Join(destDir, "existing-update"), []byte("old-content"), 0644) - c.Assert(err, IsNil) - err = ioutil.WriteFile(filepath.Join(srcDir, "existing-update"), []byte("some-new-content"), 0644) - c.Assert(err, IsNil) - - // existing file that needs no update - err = ioutil.WriteFile(filepath.Join(srcDir, "existing-unchanged"), []byte(nil), 0644) - c.Assert(err, IsNil) - err = exec.Command("cp", "-a", filepath.Join(srcDir, "existing-unchanged"), filepath.Join(destDir, "existing-unchanged")).Run() - c.Assert(err, IsNil) - - // a file that needs removal - err = ioutil.WriteFile(filepath.Join(destDir, "to-be-deleted"), []byte(nil), 0644) - c.Assert(err, IsNil) -} - -func compareDirs(c *C, srcDir, destDir string) { - d1, err := exec.Command("ls", "-al", srcDir).CombinedOutput() - c.Assert(err, IsNil) - d2, err := exec.Command("ls", "-al", destDir).CombinedOutput() - c.Assert(err, IsNil) - c.Assert(string(d1), Equals, string(d2)) - // ensure content got updated - c1, err := exec.Command("sh", "-c", fmt.Sprintf("find %s -type f |xargs cat", srcDir)).CombinedOutput() - c.Assert(err, IsNil) - c2, err := exec.Command("sh", "-c", fmt.Sprintf("find %s -type f |xargs cat", destDir)).CombinedOutput() - c.Assert(err, IsNil) - c.Assert(string(c1), Equals, string(c2)) -} - -func (ts *HTestSuite) TestSyncDirs(c *C) { - - for _, l := range [][2]string{ - [2]string{"src-short", "dst-loooooooooooong"}, - [2]string{"src-loooooooooooong", "dst-short"}, - [2]string{"src-eq", "dst-eq"}, - } { - - // ensure we have src, dest dirs with different length - srcDir := filepath.Join(c.MkDir(), l[0]) - err := os.MkdirAll(srcDir, 0755) - c.Assert(err, IsNil) - destDir := filepath.Join(c.MkDir(), l[1]) - err = os.MkdirAll(destDir, 0755) - c.Assert(err, IsNil) - - // add a src subdir - subdir := filepath.Join(srcDir, "subdir") - err = os.Mkdir(subdir, 0755) - c.Assert(err, IsNil) - makeTestFiles(c, subdir, destDir) - - // add a dst subdir that needs to get deleted - subdir2 := filepath.Join(destDir, "to-be-deleted-subdir") - err = os.Mkdir(subdir2, 0755) - subdir3 := filepath.Join(subdir2, "to-be-deleted-sub-subdir") - err = os.Mkdir(subdir3, 0755) - - // and a toplevel - makeTestFiles(c, srcDir, destDir) - - // do it - err = RSyncWithDelete(srcDir, destDir) - c.Assert(err, IsNil) - - // ensure meta-data is identical - compareDirs(c, srcDir, destDir) - compareDirs(c, filepath.Join(srcDir, "subdir"), filepath.Join(destDir, "subdir")) - } -} - -func (ts *HTestSuite) TestSyncDirFails(c *C) { - srcDir := c.MkDir() - err := os.MkdirAll(srcDir, 0755) - c.Assert(err, IsNil) - - destDir := c.MkDir() - err = os.MkdirAll(destDir, 0755) - c.Assert(err, IsNil) - - err = ioutil.WriteFile(filepath.Join(destDir, "meep"), []byte(nil), 0644) - c.Assert(err, IsNil) - - // ensure remove fails - err = os.Chmod(destDir, 0100) - c.Assert(err, IsNil) - // make tempdir cleanup work again - defer os.Chmod(destDir, 0755) - - // do it - err = RSyncWithDelete(srcDir, destDir) - c.Check(err, NotNil) - c.Check(err, ErrorMatches, ".*permission denied.*") -} diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/snappy.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/snappy.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/snappy.go 2016-04-01 09:50:49.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/snappy.go 2016-08-09 09:01:48.000000000 +0000 @@ -9,30 +9,9 @@ package main import ( - "errors" "fmt" - "io/ioutil" - "os" - "os/exec" - "os/signal" - "path/filepath" - "runtime" - "syscall" - "time" - - "github.com/ubuntu-core/snappy/arch" - "github.com/ubuntu-core/snappy/dirs" - "github.com/ubuntu-core/snappy/osutil" - "github.com/ubuntu-core/snappy/partition" - "github.com/ubuntu-core/snappy/progress" - "github.com/ubuntu-core/snappy/provisioning" - "github.com/ubuntu-core/snappy/release" - "github.com/ubuntu-core/snappy/snap" - "github.com/ubuntu-core/snappy/snappy" - "gopkg.in/yaml.v2" "launchpad.net/goget-ubuntu-touch/diskimage" - "launchpad.net/goget-ubuntu-touch/sysutils" "launchpad.net/goget-ubuntu-touch/ubuntuimage" ) @@ -79,14 +58,11 @@ } } -// Snapper holds common options applicable to snappy based images. type Snapper struct { Channel string `long:"channel" description:"Specify the channel to use" default:"stable"` Output string `long:"output" short:"o" description:"Name of the image file to create" required:"true"` - Gadget string `long:"gadget" description:"The snappy gadget package to base the image out of" default:"generic-amd64"` + Oem string `long:"oem" description:"The snappy oem package to base the image out of" default:"generic-amd64"` StoreID string `long:"store" description:"Set an alternate store id."` - OS string `long:"os" description:"path to the OS snap."` - Kernel string `long:"kernel" description:"path to the kernel snap."` Development struct { Install []string `long:"install" description:"Install additional packages (can be called multiple times)"` @@ -98,719 +74,34 @@ Release string `positional-arg-name:"release" description:"The release to base the image out of (15.04 or rolling)" required:"true"` } `positional-args:"yes" required:"yes"` - img diskimage.CoreImage - hardware diskimage.HardwareDescription - gadget diskimage.GadgetDescription - stagingRootPath string + img diskimage.CoreImage + hardware diskimage.HardwareDescription + oem diskimage.OemDescription size int64 - flavor imageFlavor - device string - + flavor imageFlavor + device string customizationFunc []func() error } -func (s Snapper) sanityCheck() error { - // we don't want to overwrite the output, people might get angry :-) - if osutil.FileExists(s.Output) { - return fmt.Errorf("Giving up, the desired target output file %#v already exists", s.Output) - } - - if s.size < s.flavor.minSize() { - return fmt.Errorf("minimum size for %s is %d", s.flavor, s.flavor.minSize()) - } - - if syscall.Getuid() != 0 { - return errors.New("command requires sudo/pkexec (root)") - } - if s.Positional.Release == "15.04" { - return errors.New("building 15.04 core images is no longer supported. Please use the ppa:snappy-dev/tools 15.04 version of this tool") - } - - return nil -} - func (s *Snapper) systemImage() (*ubuntuimage.Image, error) { - channels, err := ubuntuimage.NewChannels(globalArgs.Server) - if err != nil { - return nil, err - } - - channel := systemImageChannel(s.flavor.Channel(), s.Positional.Release, s.Channel) - // TODO: remove once azure channel is gone - if s.device == "" { - s.device = systemImageDeviceChannel(s.gadget.Architecture()) - } - - deviceChannel, err := channels.GetDeviceChannel(globalArgs.Server, channel, s.device) - if err != nil { - return nil, err - } - - systemImage, err := getImage(deviceChannel) - if err != nil { - return nil, err - } - - // avoid passing more args to setup() - globalArgs.Revision = systemImage.Version - - return &systemImage, nil -} - -func (s *Snapper) installFlags() snappy.InstallFlags { - flags := snappy.InhibitHooks | snappy.AllowGadget - - if s.Development.DeveloperMode { - flags |= snappy.AllowUnauthenticated - } - - return flags + return nil, nil } func (s *Snapper) install(systemPath string) error { - dirs.SetRootDir(systemPath) - defer dirs.SetRootDir("/") - - flags := s.installFlags() - gadgetSoftware := s.gadget.Gadget.Software - packageCount := len(s.Development.Install) + len(gadgetSoftware.BuiltIn) + len(gadgetSoftware.Preinstalled) + 3 - if s.Gadget != "" { - packageCount++ - } - - packageQueue := make([]string, 0, packageCount) - if s.Gadget != "" { - packageQueue = append(packageQueue, s.Gadget) - } - if s.OS != "" && s.Kernel != "" { - packageQueue = append(packageQueue, s.Kernel) - packageQueue = append(packageQueue, s.OS) - } - packageQueue = append(packageQueue, gadgetSoftware.BuiltIn...) - packageQueue = append(packageQueue, gadgetSoftware.Preinstalled...) - packageQueue = append(packageQueue, s.Development.Install...) - - for _, snap := range packageQueue { - fmt.Println("Installing", snap) - - pb := progress.NewTextProgress() - name := snap - if _, err := snappy.Install(name, s.Channel, flags, pb); err != nil { - return fmt.Errorf("failed to install %q from %q: %s", name, s.Channel, err) - } - } - - // set the bootvars for kernel/os snaps, the latest snappy is - // not activating the snaps on install anymore (with inhibit) - // so we need to work around that here (only on first boot) - // - // there is also no mounted os/kernel snap in the systemPath - // all we have here is the blobs - if s.OS != "" && s.Kernel != "" { - bootloader, err := partition.FindBootloader() - if err != nil { - return fmt.Errorf("can not set kernel/os bootvars: %s", err) - } - - snaps, _ := filepath.Glob(filepath.Join(dirs.SnapBlobDir, "*.snap")) - for _, fullname := range snaps { - bootvar := "" - - // detect type - snapFile, err := snap.Open(fullname) - if err != nil { - return fmt.Errorf("can not read %v", fullname) - } - info, err := snapFile.Info() - if err != nil { - return fmt.Errorf("can not get info for %v", fullname) - } - switch info.Type { - case snap.TypeOS: - bootvar = "snappy_os" - case snap.TypeKernel: - bootvar = "snappy_kernel" - } - - name := filepath.Base(fullname) - if bootvar != "" { - if err := bootloader.SetBootVar(bootvar, name); err != nil { - return err - } - } - } - - // HORRIBLE, snappy.Install() will check if running - // on a grub system based on the gadget snap and if - // it is grub it will not extract the kernel/os - // - // HOWEVER this won't work in u-d-f because there - // is no current symlink so kernel.go always unpacks - // the kernel. undo this here - if s.gadget.Gadget.Hardware.Bootloader == "grub" { - dirs, _ := filepath.Glob(filepath.Join(s.img.Boot(), "/EFI/ubuntu/grub/*.snap")) - for _, d := range dirs { - fmt.Printf("Removing unneeded: %s\n", d) - if err := os.RemoveAll(d); err != nil { - return err - } - } - } - } - - return nil -} - -func (s *Snapper) extractGadget(gadgetPackage string) error { - if gadgetPackage == "" { - return nil - } - - tempDir, err := ioutil.TempDir("", "gadget") - if err != nil { - return err - } - - // we need to fix the permissions for tempdir to be seteuid friendly - if err := os.Chmod(tempDir, 0755); err != nil { - return err - } - - s.stagingRootPath = tempDir - os.MkdirAll(filepath.Join(tempDir, "/snaps"), 0755) - - dirs.SetRootDir(tempDir) - defer dirs.SetRootDir("/") - release.Override(release.Release{ - Flavor: string(s.flavor), - Series: s.Positional.Release, - Channel: s.Channel, - }) - - // we need to download and extract the squashfs snap - downloadedSnap := gadgetPackage - if !osutil.FileExists(gadgetPackage) { - repo := snappy.NewConfiguredUbuntuStoreSnapRepository() - snap, err := repo.Snap(gadgetPackage, s.Channel) - if err != nil { - return fmt.Errorf("expected a gadget snaps: %s", err) - } - - pb := progress.NewTextProgress() - downloadedSnap, err = repo.Download(snap, pb) - if err != nil { - return err - } - } - - // the fake snap needs to be in an expected location so that - // s.loadGadget() is happy - fakeGadgetDir := filepath.Join(tempDir, "/gadget/fake-gadget/1.0-fake/") - if err := os.MkdirAll(fakeGadgetDir, 0755); err != nil { - return err - } - cmd := exec.Command("unsquashfs", "-f", "-d", fakeGadgetDir, downloadedSnap) - if output, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("snap unpack failed with: %v (%v)", err, string(output)) - } - - if err := s.loadGadget(tempDir); err != nil { - return err - } - - return nil -} - -func (s *Snapper) loadGadget(systemPath string) error { - pkgs, err := filepath.Glob(filepath.Join(systemPath, "/gadget/*/*/meta/snap.yaml")) - if err != nil { - return err - } - - // checking for len(pkgs) > 2 due to the 'current' symlink - if len(pkgs) == 0 { - return errors.New("no gadget package found") - } else if len(pkgs) > 2 || err != nil { - return errors.New("too many gadget packages installed") - } - - f, err := ioutil.ReadFile(pkgs[0]) - if err != nil { - return errors.New("failed to read gadget yaml") - } - - var gadget diskimage.GadgetDescription - if err := yaml.Unmarshal([]byte(f), &gadget); err != nil { - return errors.New("cannot decode gadget yaml") - } - s.gadget = gadget - s.gadget.SetRoot(systemPath) - - // ensure we can download and install snaps - arch.SetArchitecture(arch.ArchitectureType(s.gadget.Architecture())) - return nil } -// Creates a YAML file inside the image that contains metadata relating -// to the installation. -func (s Snapper) writeInstallYaml(bootMountpoint string) error { - selfPath, err := exec.LookPath(os.Args[0]) - if err != nil { - return err - } - - bootDir := "" - - switch s.gadget.Gadget.Hardware.Bootloader { - // Running systems use a bindmount for /boot/grub, but - // since the system isn't booted, create the file in the - // real location. - case "grub": - bootDir = "/EFI/ubuntu/grub" - } - - installYamlFilePath := filepath.Join(bootMountpoint, bootDir, provisioning.InstallYamlFile) - - i := provisioning.InstallYaml{ - InstallMeta: provisioning.InstallMeta{ - Timestamp: time.Now(), - }, - InstallTool: provisioning.InstallTool{ - Name: filepath.Base(selfPath), - Path: selfPath, - // FIXME: we don't know our own version yet :) - // Version: "???", - }, - InstallOptions: provisioning.InstallOptions{ - Size: s.size, - SizeUnit: "GB", - Output: s.Output, - Channel: s.Channel, - DevicePart: s.Development.DevicePart, - Gadget: s.Gadget, - OS: s.OS, - Kernel: s.Kernel, - DeveloperMode: s.Development.DeveloperMode, - }, - } - - data, err := yaml.Marshal(&i) - if err != nil { - return err - } - - // the file isn't supposed to be modified, hence r/o. - return ioutil.WriteFile(installYamlFilePath, data, 0444) -} - -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 { - runtime.GOMAXPROCS(1) - runtime.LockOSThread() - - if err := sysutils.DropPrivs(); err != nil { - return hw, err - } - } - - printOut("Searching for hardware.yaml in device part") - tmpdir, err := ioutil.TempDir("", "hardware") - if err != nil { - return hw, errors.New("cannot create tempdir to extract hardware.yaml from device part") - } - defer os.RemoveAll(tmpdir) - - if out, err := exec.Command("tar", "xf", path, "-C", tmpdir, "hardware.yaml").CombinedOutput(); err != nil { - return hw, fmt.Errorf("failed to extract a hardware.yaml from the device part: %s", out) - } - - data, err := ioutil.ReadFile(filepath.Join(tmpdir, "hardware.yaml")) - if err != nil { - return hw, err - } - - err = yaml.Unmarshal([]byte(data), &hw) - - return hw, err -} - -func (s *Snapper) bindMount(d string) (string, error) { - src := filepath.Join(s.img.Writable(), "system-data", d) - dst := filepath.Join(s.img.System(), d) - - if err := os.MkdirAll(src, 0755); err != nil { - return "", err - } - cmd := exec.Command("mount", "--bind", src, dst) - if o, err := cmd.CombinedOutput(); err != nil { - return "", fmt.Errorf("bind mount failed for %s to %s with: %s %v ", src, dst, err, string(o)) - } - return dst, nil -} - -func (s *Snapper) downloadOS(osPackage string) (string, error) { - if osPackage == "" { - return "", nil - } - // if its pointing to a local file, just return that - if _, err := os.Stat(osPackage); err == nil { - return osPackage, nil - } - - release.Override(release.Release{ - Flavor: string(s.flavor), - Series: s.Positional.Release, - Channel: s.Channel, - }) - m := snappy.NewConfiguredUbuntuStoreSnapRepository() - snap, err := m.Snap(osPackage, s.Channel) - if err != nil { - return "", fmt.Errorf("failed to find os snap: %s", err) - } - pb := progress.NewTextProgress() - path, err := m.Download(snap, pb) - if err != nil { - return "", err - } - - return path, nil -} - -func (s *Snapper) setup(systemImageFiles []Files) error { - printOut("Mounting...") - if err := s.img.Mount(); err != nil { - return err - } - defer func() { - printOut("Unmounting...") - if err := s.img.Unmount(); err != nil { - fmt.Println("WARNING: unexpected issue:", err) - } - }() - - printOut("Provisioning...") - for i := range systemImageFiles { - if out, err := exec.Command("fakeroot", "tar", "--numeric-owner", "-axvf", systemImageFiles[i].FilePath, "-C", s.img.BaseMount()).CombinedOutput(); err != nil { - printOut(string(out)) - return fmt.Errorf("issues while extracting: %s", out) - } - } - - systemPath := s.img.System() - - // setup a fake system - if s.gadget.PartitionLayout() == "minimal" { - if err := os.MkdirAll(systemPath, 0755); err != nil { - return err - } - - // this is a bit terrible, we need to download the OS - // mount it, "sync dirs" (see below) and then we - // will need to download it again to install it properly - osSnap, err := s.downloadOS(s.OS) - if err != nil { - return err - } - - // mount os snap - cmd := exec.Command("mount", osSnap, systemPath) - if o, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("os snap mount failed with: %s %v ", err, string(o)) - } - defer exec.Command("umount", systemPath).Run() - - // we need to do what "writable-paths" normally does on - // boot for etc/systemd/system, i.e. copy all the stuff - // from the os into the writable partition. normally - // this is the job of the initrd, however it won't touch - // the dir if there are files in there already. and a - // kernel/os install will create auto-mount units in there - src := filepath.Join(systemPath, "etc", "systemd", "system") - dst := filepath.Join(s.img.Writable(), "system-data", "etc", "systemd") - if err := os.MkdirAll(dst, 0755); err != nil { - return err - } - cmd = exec.Command("cp", "-a", src, dst) - if o, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("copy failed: %s %s", err, o) - } - - // bind mount all relevant dirs - for _, d := range []string{"snaps", "var/lib/snaps", "var/lib/snappy", "etc/systemd/system/", "tmp"} { - dst, err := s.bindMount(d) - if err != nil { - return err - } - defer exec.Command("umount", dst).Run() - } - - // bind mount /boot/efi - dst = filepath.Join(systemPath, "/boot/efi") - cmd = exec.Command("mount", "--bind", s.img.Boot(), dst) - if o, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("boot bind mount failed with: %s %v ", err, string(o)) - } - defer exec.Command("umount", dst).Run() - switch s.gadget.Gadget.Hardware.Bootloader { - case "grub": - // grub needs this - grubUbuntu := filepath.Join(s.img.Boot(), "EFI/ubuntu/grub") - os.MkdirAll(grubUbuntu, 0755) - - // and /boot/grub - src = grubUbuntu - dst = filepath.Join(systemPath, "/boot/grub") - cmd = exec.Command("mount", "--bind", src, dst) - if o, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("boot/ubuntu bind mount failed with: %s %v ", err, string(o)) - } - defer exec.Command("umount", dst).Run() - - // TERRIBLE but we need a /boot/grub/grub.cfg so that - // the kernel and os snap can be installed - glob, err := filepath.Glob(filepath.Join(s.stagingRootPath, "gadget", "*", "*", "grub.cfg")) - if err != nil { - return fmt.Errorf("grub.cfg glob failed: %s", err) - } - if len(glob) != 1 { - return fmt.Errorf("can not find a valid grub.cfg, found %v instead", len(glob)) - } - gadgetGrubCfg := glob[0] - cmd = exec.Command("cp", gadgetGrubCfg, grubUbuntu) - o, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("failed to copy %s %s", err, o) - } - case "u-boot": - src = s.img.Boot() - dst = filepath.Join(systemPath, "/boot/uboot") - cmd = exec.Command("mount", "--bind", src, dst) - if o, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("boot/ubuntu bind mount failed with: %s %v ", err, string(o)) - } - defer exec.Command("umount", dst).Run() - } - } - - if err := s.img.SetupBoot(); err != nil { - return err - } - - if err := s.install(systemPath); err != nil { - return err - } - - for i := range s.customizationFunc { - if err := s.customizationFunc[i](); err != nil { - return err - } - } - - return s.writeInstallYaml(s.img.Boot()) -} - // deploy orchestrates the priviledged part of the setup -func (s *Snapper) deploy(systemImageFiles []Files) error { - // hack to circumvent https://code.google.com/p/go/issues/detail?id=1435 - runtime.GOMAXPROCS(1) - runtime.LockOSThread() - if err := sysutils.EscalatePrivs(); err != nil { - return err - } - defer sysutils.DropPrivs() - - printOut("Formatting...") - if err := s.img.Format(); err != nil { - return err - } - - if err := s.setup(systemImageFiles); err != nil { - return err - } - +func (s *Snapper) deploy(systemImage *ubuntuimage.Image, filePathChan <-chan string) error { return nil } -func (s Snapper) printSummary() { - fmt.Println("New image complete") - fmt.Println("Summary:") - fmt.Println(" Output:", s.Output) - fmt.Println(" Architecture:", s.gadget.Architecture()) - fmt.Println(" Channel:", s.Channel) - fmt.Println(" Version:", globalArgs.Revision) -} - -func (s *Snapper) getSystemImage() ([]Files, error) { - var devicePart string - if s.Development.DevicePart != "" { - p, err := expandFile(s.Development.DevicePart) - if err != nil { - return nil, err - } - - fmt.Println("Using a custom OS or Kernel part will prevent updates for these components") - - devicePart = p - } - - fmt.Println("Fetching information from server...") - systemImage, err := s.systemImage() - if err != nil { - return nil, err - } - - filesChan := make(chan Files, len(systemImage.Files)) - sigFiles := ubuntuimage.GetGPGFiles() - - fmt.Println("Downloading and setting up...") - - go func() { - sigFilesChan := make(chan Files, len(sigFiles)) - defer close(sigFilesChan) - - for _, f := range sigFiles { - bitDownloader(f, sigFilesChan, globalArgs.Server, cacheDir) - } - }() - - filePaths := make([]Files, 0, len(systemImage.Files)) - hwChan := make(chan diskimage.HardwareDescription) - - go func() { - for i := 0; i < len(systemImage.Files); i++ { - f := <-filesChan - - if isDevicePart(f.FilePath) { - devicePart = f.FilePath - - if hardware, err := extractHWDescription(f.FilePath); err != nil { - fmt.Println("Failed to read harware.yaml from device part, provisioning may fail:", err) - } else { - hwChan <- hardware - } - } - - printOut("Download finished for", f.FilePath) - filePaths = append(filePaths, f) - } - close(hwChan) - close(filesChan) - }() - - for _, f := range systemImage.Files { - if devicePart != "" && isDevicePart(f.Path) { - printOut("Using a custom device tarball") - filesChan <- Files{FilePath: devicePart} - } else { - go bitDownloader(f, filesChan, globalArgs.Server, cacheDir) - } - } - - s.hardware = <-hwChan - - return filePaths, nil -} - -func (s *Snapper) create() (err error) { - if err := s.sanityCheck(); err != nil { - return err - } - - if s.StoreID != "" { - fmt.Println("Setting store id to", s.StoreID) - os.Setenv("UBUNTU_STORE_ID", s.StoreID) - } - - fmt.Println("Determining gadget configuration") - if err := s.extractGadget(s.Gadget); err != nil { - return err - } - defer os.RemoveAll(s.stagingRootPath) - - // hack to circumvent https://code.google.com/p/go/issues/detail?id=1435 - runtime.GOMAXPROCS(1) - runtime.LockOSThread() - if err := sysutils.DropPrivs(); err != nil { - return err - } - - systemImageFiles := []Files{} - switch s.gadget.Gadget.Hardware.PartitionLayout { - case "minimal": - if s.OS == "" && s.Kernel == "" { - return errors.New("kernel and os have to be specified to support partition-layout: minimal") - } - } - - switch s.gadget.Gadget.Hardware.Bootloader { - case "grub": - legacy := isLegacy(s.Positional.Release, s.Channel, globalArgs.Revision) - if legacy { - printOut("Using legacy setup") - } - - s.img = diskimage.NewCoreGrubImage(s.Output, s.size, s.flavor.rootSize(), s.hardware, s.gadget, legacy, "gpt") - case "u-boot": - label := "msdos" - if s.gadget.Architecture() == archArm64 { - label = "gpt" - } - s.img = diskimage.NewCoreUBootImage(s.Output, s.size, s.flavor.rootSize(), s.hardware, s.gadget, label) - default: - return errors.New("no hardware description in Gadget snap") - } - - printOut("Partitioning...") - if err := s.img.Partition(); err != nil { - return err - } - defer func() { - if err != nil { - os.Remove(s.Output) - } - }() - - // Handle SIGINT and SIGTERM. - go func() { - ch := make(chan os.Signal) - signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) - - for sig := range ch { - printOut("Received", sig, "... ignoring") - } - }() - - // Execute the following code with escalated privs and drop them when done - if err := s.deploy(systemImageFiles); err != nil { - return err - } - - if err := s.img.FlashExtra(); err != nil { - return err - } - - s.printSummary() - - return nil -} - -func isLegacy(release, channel string, revision int) bool { - if release != "15.04" { - return false - } - - switch channel { - case "edge": - return revision <= 149 - case "alpha": - return revision <= 9 - case "stable": - return revision <= 4 - } +func (s *Snapper) create() error { + return fmt.Errorf(`Building core images is currently not supported. - return false +Images for ubuntu-core 15.04 can be build with the ppa:snappy-dev/tools. +Building images for ubuntu-core 16.04 will be supported by this tool soon. +`) } diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/snappy_test.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/snappy_test.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/snappy_test.go 2016-03-29 15:39:25.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/snappy_test.go 2016-08-09 09:01:48.000000000 +0000 @@ -31,19 +31,3 @@ type SnappyTestSuite struct{} var _ = Suite(&SnappyTestSuite{}) - -func (s *SnappyTestSuite) TestLegacy(c *C) { - c.Check(isLegacy("rolling", "edge", 1), Equals, false) - - c.Check(isLegacy("15.04", "edge", 1), Equals, true) - c.Check(isLegacy("15.04", "edge", 149), Equals, true) - c.Check(isLegacy("15.04", "edge", 150), Equals, false) - - c.Check(isLegacy("15.04", "alpha", 1), Equals, true) - c.Check(isLegacy("15.04", "alpha", 9), Equals, true) - c.Check(isLegacy("15.04", "alpha", 10), Equals, false) - - c.Check(isLegacy("15.04", "stable", 1), Equals, true) - c.Check(isLegacy("15.04", "stable", 4), Equals, true) - c.Check(isLegacy("15.04", "stable", 5), Equals, false) -} diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/touch.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/touch.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-device-flash/touch.go 2016-04-01 10:33:39.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-device-flash/touch.go 2016-08-09 09:01:48.000000000 +0000 @@ -2,7 +2,7 @@ // ubuntu-device-flash - Tool to download and flash devices with an Ubuntu Image // based system // -// Copyright (c) 2013-2014 Canonical Ltd. +// Copyright (c) 2013-2016 Canonical Ltd. // // Written by Sergio Schvezov // @@ -35,13 +35,14 @@ Bootstrap bool `long:"bootstrap" description:"bootstrap the system, do this from the bootloader"` Wipe bool `long:"wipe" description:"Clear all data after flashing"` Serial string `long:"serial" description:"Serial of the device to operate"` + AdbSerial string `long:"adb-serial" description:"Serial for ADB to specify the device to operate"` DeveloperMode bool `long:"developer-mode" description:"Enables developer mode after the factory reset, this is meant for automation and makes the device insecure by default (requires --password)"` AdbKeys string `long:"adb-keys" description:"Specify a local adb keys files, instead of using default ~/.android/adbkey.pub (requires --developer-mode)"` DeviceTarball string `long:"device-tarball" description:"Specify a local device tarball to override the one from the server (using official Ubuntu images with different device tarballs)"` CustomTarball string `long:"custom-tarball" description:"Specify a local custom tarball to override the one from the server (using official Ubuntu images with different custom tarballs)"` RunScript string `long:"run-script" description:"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)"` Password string `long:"password" description:"This sets up the default password for the phablet user. This option is meant for CI and not general use"` - Channel string `long:"channel" description:"Specify the channel to use" default:"ubuntu-touch/stable"` + Channel string `long:"channel" description:"Specify the channel to use" default:"ubuntu-touch/stable/ubuntu"` Device string `long:"device" description:"Specify the device to flash"` RecoveryImage string `long:"recovery-image" description:"Specify the recovery image file to use when flashing, overriding the one from the device tarball (useful if the latter has no adb enabled)"` fastboot devices.Fastboot @@ -116,6 +117,11 @@ fmt.Println("WARNING: --adb-keys is dangerous, potentially authorising multiple cliets to connect to your device") } + // print out a conditional warning for devel* channel usage + if strings.HasPrefix(touchCmd.Channel, "ubuntu-touch/devel") { + fmt.Println("WARNING You are about to flash your phone with a development image - continue at your own risk! There is absolutely no guarantee that even the most basic phone functions will work.") + } + var deviceTarballPath string if touchCmd.DeviceTarball != "" { p, err := expandFile(touchCmd.DeviceTarball) @@ -229,17 +235,60 @@ if err := touchCmd.fastboot.Flash("recovery", recovery); err != nil { return errors.New("can't flash recovery image") } - if err := touchCmd.fastboot.Format("cache"); err != nil { - log.Print("Cache formatting was not successful, flashing may fail, " + - "check your partitions on device") + + var deviceSupportsCacheFormat bool = true + var deviceSupportsBootImage bool = true + var deviceSupportsOemRebootRecovery bool = false + + if touchCmd.Device == "turbo" { + deviceSupportsCacheFormat = false + deviceSupportsBootImage = false + deviceSupportsOemRebootRecovery = true + } + if touchCmd.Device == "frieza" || touchCmd.Device == "cooler" { + deviceSupportsCacheFormat = false + } + + if deviceSupportsCacheFormat { + if err := touchCmd.fastboot.Format("cache"); err != nil { + log.Print("Cache formatting was not successful, flashing may fail, " + + "check your partitions on device") + } } - if err := touchCmd.fastboot.BootImage(recovery); err != nil { - return errors.New("Can't boot recovery image") + if deviceSupportsBootImage { + if err := touchCmd.fastboot.BootImage(recovery); err != nil { + return errors.New("Can't boot recovery image") + } + } else if deviceSupportsOemRebootRecovery { + // Some bootloaders does not support the BootImage command so we have + // to flash the recovery first and then reboot through a OEM specific + // command the bootloader offers. + if err := touchCmd.fastboot.SendOemCommand("reboot recovery"); err != nil { + return errors.New("Can't reboot device") + } + } else { + log.Print("We can't reboot your device automatically. Please reboot " + + "your device manually to recovery mode.") } + + log.Print("Waiting for device to enter recovery mode ...") if err := touchCmd.adb.WaitForRecovery(); err != nil { return err } + + if !deviceSupportsCacheFormat { + // On some devices we can't run `fastboot format cache` as the bootloader + // does not support this command. We're erasing all bits from the + // cache partition manually once we've booted into the recovery. + if _, err := touchCmd.adb.Shell("rm -rf /cache/*"); err != nil { + log.Fatal("Cannot cleanup /cache/ to ensure clean deployment", err) + } + + if _, err := touchCmd.adb.Shell("mkdir /cache/recovery"); err != nil { + log.Fatal("Failed to recreate filesystem structure on cache partition", err) + } + } } go bitPusher(touchCmd.adb, files, done) for i := 0; i < totalFiles; i++ { @@ -304,10 +353,24 @@ touchCmd.fastboot.SetSerial(touchCmd.Serial) } + if touchCmd.AdbSerial != "" { + touchCmd.adb.SetSerial(touchCmd.AdbSerial) + } + if touchCmd.Device == "" { if touchCmd.Bootstrap { log.Print("Expecting the device to be in the bootloader... waiting") touchCmd.Device, err = touchCmd.fastboot.GetDevice() + + // For turbo it was missed to put the proper name into the bootloader + // and this can't be changed anymore after production already started. + // Reflashing the bootloader through an OTA update to fix this is also + // very unlikely to happen so we have to work around here and make sure + // this never happens again. + if touchCmd.Device == "smdk" { + touchCmd.Device = "turbo" + } + return err } else { log.Print("Expecting the device to expose an adb interface...") diff -Nru goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-emulator/create.go goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-emulator/create.go --- goget-ubuntu-touch-0.33-0ubuntu1~xenial/ubuntu-emulator/create.go 2016-03-29 15:39:25.000000000 +0000 +++ goget-ubuntu-touch-0.34+16.10.20160805/ubuntu-emulator/create.go 2016-08-09 09:01:48.000000000 +0000 @@ -49,7 +49,7 @@ var createCmd CreateCmd const ( - defaultChannel = "ubuntu-touch/devel" + defaultChannel = "ubuntu-touch/stable" defaultServer = "https://system-image.ubuntu.com" defaultArch = "i386" )