blob: d09ce48f60d133e7efee2e1e709f97f89e0f0632 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package builder
import (
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"mynewt.apache.org/newt/newt/pkg"
"mynewt.apache.org/newt/newt/project"
"mynewt.apache.org/newt/util"
)
func (t *TargetBuilder) loadLoader(slot int, extraJtagCmd string, imgFilename string) error {
if err := t.bspPkg.Reload(t.LoaderBuilder.cfg.SettingValues()); err != nil {
return err
}
return t.LoaderBuilder.Load(slot, extraJtagCmd, imgFilename)
}
func (t *TargetBuilder) loadApp(slot int, extraJtagCmd string, imgFilename string) error {
if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
return err
}
return t.AppBuilder.Load(slot, extraJtagCmd, imgFilename)
}
func (t *TargetBuilder) debugLoader(extraJtagCmd string, reset bool,
noGDB bool, elfBase string) error {
if err := t.bspPkg.Reload(t.LoaderBuilder.cfg.SettingValues()); err != nil {
return err
}
return t.LoaderBuilder.Debug(extraJtagCmd, reset, noGDB, elfBase)
}
func (t *TargetBuilder) debugApp(extraJtagCmd string, reset bool,
noGDB bool, elfBase string) error {
if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
return err
}
return t.AppBuilder.Debug(extraJtagCmd, reset, noGDB, elfBase)
}
// Load loads a .img file onto a device. If imgFileOverride is not empty, it
// specifies the path of the image file to load. If it is empty, the image in
// the target's `bin` directory is loaded.
func (t *TargetBuilder) Load(extraJtagCmd string, imgFileOverride string) error {
err := t.PrepBuild()
if err != nil {
return err
}
if t.LoaderBuilder != nil && imgFileOverride != "" {
return util.FmtNewtError(
"cannot specify image file override for split images")
}
appImg := imgFileOverride
if appImg == "" {
appImg = t.AppBuilder.AppBinBasePath()
}
if t.LoaderBuilder != nil {
err = t.loadApp(1, extraJtagCmd, appImg)
if err == nil {
err = t.loadLoader(0, extraJtagCmd, t.LoaderBuilder.AppBinBasePath())
}
} else {
err = t.loadApp(0, extraJtagCmd, appImg)
}
return err
}
func RunOptionalCheck(checkScript string, env map[string]string) error {
if checkScript == "" {
return nil
}
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM)
cmd := []string{
checkScript,
}
/* Handle Ctrl-C, terminate newt, as it is the
intended behavior */
go func() {
sig := <-sigs
fmt.Println(sig)
os.Exit(0)
}()
util.StatusMessage(util.VERBOSITY_SILENT,
"Optional target check: %s\n", strings.Join(cmd, " "))
util.ShellInteractiveCommand(cmd, env, true)
/* Unregister SIGTERM handler */
signal.Reset(syscall.SIGTERM)
return nil
}
func Load(binBasePath string, bspPkg *pkg.BspPackage,
extraEnvSettings map[string]string) error {
if bspPkg.DownloadScript == "" {
return nil
}
env := BasicEnvVars(binBasePath, bspPkg)
for k, v := range extraEnvSettings {
env[k] = v
}
RunOptionalCheck(bspPkg.OptChkScript, env)
// bspPath, binBasePath are passed in command line for backwards
// compatibility
cmd := []string{
bspPkg.DownloadScript,
bspPkg.BasePath(),
binBasePath,
}
util.StatusMessage(util.VERBOSITY_VERBOSE, "Load command: %s\n",
strings.Join(cmd, " "))
util.StatusMessage(util.VERBOSITY_VERBOSE, "Environment:\n")
for _, v := range env {
util.StatusMessage(util.VERBOSITY_VERBOSE, "* %s\n", v)
}
if _, err := util.ShellCommand(cmd, env); err != nil {
return err
}
util.StatusMessage(util.VERBOSITY_VERBOSE, "Successfully loaded image.\n")
return nil
}
func (b *Builder) Load(imageSlot int, extraJtagCmd string, imgFilename string) error {
if b.appPkg == nil {
return util.NewNewtError("app package not specified")
}
/* Populate the package list and feature sets. */
err := b.targetBuilder.PrepBuild()
if err != nil {
return err
}
env, err := b.EnvVars(imageSlot)
if err != nil {
return err
}
if extraJtagCmd != "" {
env["EXTRA_JTAG_CMD"] = extraJtagCmd
}
if _, ok := env["BOOT_LOADER"]; ok {
util.StatusMessage(util.VERBOSITY_DEFAULT,
"Loading bootloader (%s)\n", imgFilename)
} else {
util.StatusMessage(util.VERBOSITY_DEFAULT,
"Loading %s image into slot %d (%s)\n", b.buildName, imageSlot+1, imgFilename)
}
// Convert the binary path from absolute to relative. This is required for
// compatibility with unix-in-windows environemnts (e.g., cygwin).
binPath := util.TryRelPath(imgFilename)
if err := Load(binPath, b.targetBuilder.bspPkg, env); err != nil {
return err
}
return nil
}
// Debug runs gdb on the .elf file corresponding to what is running on a
// device. If elfFileOverride is not empty, it specifies the path of the .elf
// file to debug. If it is empty, the .elf file in the target's `bin`
// directory is loaded.
func (t *TargetBuilder) Debug(extraJtagCmd string, reset bool, noGDB bool, elfFileOverride string) error {
if err := t.PrepBuild(); err != nil {
return err
}
var elfBase string // Everything except ".elf"
if elfFileOverride != "" {
// The debug script appends ".elf" to the basename. Make sure we can strip
// the extension here and the script will reconstruct the original
// filename.
elfBase = strings.TrimSuffix(elfFileOverride, ".elf")
if elfBase == elfFileOverride {
return util.FmtNewtError(
"invalid elf filename: must end in \".elf\": filename=%s",
elfFileOverride)
}
}
if t.LoaderBuilder == nil {
if elfBase == "" {
elfBase = t.AppBuilder.AppBinBasePath()
}
return t.debugApp(extraJtagCmd, reset, noGDB, elfBase)
} else {
if elfBase == "" {
elfBase = t.LoaderBuilder.AppBinBasePath()
}
return t.debugLoader(extraJtagCmd, reset, noGDB, elfBase)
}
}
func (b *Builder) debugBin(binPath string, extraJtagCmd string, reset bool,
noGDB bool) error {
/*
* Populate the package list and feature sets.
*/
err := b.targetBuilder.PrepBuild()
if err != nil {
return err
}
bspPath := b.bspPkg.rpkg.Lpkg.BasePath()
binBasePath := binPath
bspPkg := b.targetBuilder.bspPkg
env, err := b.EnvVars(0)
if err != nil {
return err
}
// Make sure the elf override (if any) gets used.
env["BIN_BASENAME"] = binPath
if extraJtagCmd != "" {
env["EXTRA_JTAG_CMD"] = extraJtagCmd
}
if reset == true {
env["RESET"] = "true"
}
if noGDB == true {
env["NO_GDB"] = "1"
}
os.Chdir(project.GetProject().Path())
RunOptionalCheck(bspPkg.OptChkScript, env)
// bspPath, binBasePath are passed in command line for backwards
// compatibility
cmdLine := []string{
b.targetBuilder.bspPkg.DebugScript, bspPath, binBasePath,
}
fmt.Printf("%s\n", cmdLine)
return util.ShellInteractiveCommand(cmdLine, env, false)
}
func (b *Builder) Debug(extraJtagCmd string, reset bool, noGDB bool, binBase string) error {
return b.debugBin(binBase, extraJtagCmd, reset, noGDB)
}