Merge "platform: add jsonpoll to platform Makefile"
diff --git a/cmds/logos.c b/cmds/logos.c
index 5a7f426..2f453d0 100644
--- a/cmds/logos.c
+++ b/cmds/logos.c
@@ -702,6 +702,7 @@
         ssize_t linelen = p - start;
         suppress_mac_addresses(start, linelen, ':');
         suppress_mac_addresses(start, linelen, '-');
+        suppress_mac_addresses(start, linelen, '_');
         suppress_media_filenames(start, linelen, "/var/media/pictures/");
         suppress_media_filenames(start, linelen, "/var/media/videos/");
         flush(header, headerlen, start, linelen);
diff --git a/jsonpoll/jsonpoll.py b/jsonpoll/jsonpoll.py
index dbdbc85..9e78b8e 100755
--- a/jsonpoll/jsonpoll.py
+++ b/jsonpoll/jsonpoll.py
@@ -23,7 +23,6 @@
 import sys
 import tempfile
 import time
-import urllib
 import urllib2
 import options
 
@@ -31,8 +30,9 @@
 optspec = """
 jsonpoll [options]
 --
-h,host=      host to connect to [localhost]
-p,port=      port to connect to [8000]
+host=            host to connect to [localhost]
+port=            port to connect to [8000]
+i,interval=      poll interval in seconds [15]
 """
 
 
@@ -44,31 +44,28 @@
   # os.rename() when moving files into the final destination.
   OUTPUT_DIR = '/tmp/glaukus/'
 
-  # The time to wait between requests.
-  _DURATION_BETWEEN_POLLS_SECS = 15
-
   # The time to wait before giving up on blocking connection operations.
   _SOCKET_TIMEOUT_SECS = 15
 
-  def __init__(self, host, port):
+  def __init__(self, host, port, interval):
     self.hostport = 'http://%s:%d' % (host, port)
+
+    # The time to wait between requests in seconds.
+    self.poll_interval_secs = interval
+
     # TODO(cgibson): Support more request types once Glaukus Manager's JSON spec
     # is more stable.
-    self.report_output_file = os.path.join(self.OUTPUT_DIR, 'report.json')
-    self.paths_to_statfiles = {'info/report': self.report_output_file}
+    self.api_modem_output_file = os.path.join(self.OUTPUT_DIR, 'modem.json')
+    self.paths_to_statfiles = {'api/modem': self.api_modem_output_file}
     self.last_response = None
 
   def RequestStats(self):
-    """Sends a request via HTTP POST to the specified web server."""
+    """Sends a request via HTTP GET to the specified web server."""
     for path, output_file in self.paths_to_statfiles.iteritems():
       url = '%s/%s' % (self.hostport, path)
-      # TODO(cgibson): POST data might need to get folded into the dict somehow
-      # once we know a bit more about the actual Glaukus implementation works
-      # and what real requests will look like.
-      post_data = {'info': None}
       tmpfile = ''
       try:
-        response = self.GetHttpResponse(url, post_data, output_file)
+        response = self.GetHttpResponse(url)
         if not response:
           return False
         elif self.last_response == response:
@@ -96,14 +93,11 @@
         if os.path.exists(tmpfile):
           os.unlink(tmpfile)
 
-  def GetHttpResponse(self, url, post_data, output_file):
+  def GetHttpResponse(self, url):
     """Creates a request and retrieves the response from a web server."""
-    print 'Connecting to %s, post_data:%s, output_file:%s' % (url, post_data,
-                                                              output_file)
-    data = urllib.urlencode(post_data)
-    req = urllib2.Request(url, data)
+    print 'Connecting to %s' % url
     try:
-      handle = urllib2.urlopen(req, timeout=self._SOCKET_TIMEOUT_SECS)
+      handle = urllib2.urlopen(url, timeout=self._SOCKET_TIMEOUT_SECS)
       response = handle.read()
     except socket.timeout as ex:
       print ('Connection to %s timed out after %d seconds: %s'
@@ -128,13 +122,13 @@
   def RunForever(self):
     while True:
       self.RequestStats()
-      time.sleep(self._DURATION_BETWEEN_POLLS_SECS)
+      time.sleep(self.poll_interval_secs)
 
 
 def main():
   o = options.Options(optspec)
   (opt, unused_flags, unused_extra) = o.parse(sys.argv[1:])
-  poller = JsonPoll(opt.host, opt.port)
+  poller = JsonPoll(opt.host, opt.port, opt.interval)
   poller.RunForever()
 
 
diff --git a/jsonpoll/jsonpoll_test.py b/jsonpoll/jsonpoll_test.py
index 1fd9571..ccd05ad 100644
--- a/jsonpoll/jsonpoll_test.py
+++ b/jsonpoll/jsonpoll_test.py
@@ -74,7 +74,7 @@
 class FakeJsonPoll(jsonpoll.JsonPoll):
   """Mock JsonPoll."""
 
-  def GetHttpResponse(self, unused_url, unused_postdata, unused_output_file):
+  def GetHttpResponse(self, unused_url):
     self.get_response_called = True
     return json.dumps(JSON_RESPONSE)
 
@@ -83,7 +83,7 @@
 
   def setUp(self):
     self.CreateTempFile()
-    self.poller = FakeJsonPoll('fakehost.blah', 31337)
+    self.poller = FakeJsonPoll('fakehost.blah', 31337, 1)
 
   def tearDown(self):
     self.DeleteTempFile()
diff --git a/libstacktrace/stacktrace.c b/libstacktrace/stacktrace.c
index 85e8c1b..cf7b283 100644
--- a/libstacktrace/stacktrace.c
+++ b/libstacktrace/stacktrace.c
@@ -19,7 +19,7 @@
 }
 
 #define WRITELEN(s, l) do {if (write(2, s, l)) {}} while (0)
-#define WRITE(s) do {if (write(2, s, sizeof(s))) {}} while (0)
+#define WRITE(s) do {if (write(2, s, safe_strlen(s))) {}} while (0)
 #define WRITEINT(i) { \
     char *str = format_uint(i); \
     WRITELEN(str, safe_strlen(str)); \
diff --git a/signing/repack.py b/signing/repack.py
index 4e06fc1..031b20d 100755
--- a/signing/repack.py
+++ b/signing/repack.py
@@ -55,6 +55,7 @@
 o,hostdir=        host directory
 b,bindir=         binary directory
 s,sign            sign image with production key
+bolt_sign         sign a bolt image
 t,signing_tool=   tool to call to do the signing [brcm_sign_enc]
 q,quiet           suppress print
 """
@@ -126,8 +127,10 @@
     f.write(c)
 
 
-def RealSign(hostdir, key, ifname, ofname, signing_tool):
+def RealSign(bindir, hostdir, key, ifname, ofname, signing_tool):
   """Sign the image with production key."""
+  olddir = os.getcwd()
+  os.chdir(os.path.join(bindir, 'signing'))
   p = subprocess.Popen([os.path.join(hostdir, 'usr/bin', signing_tool)],
                        stdin=subprocess.PIPE, shell=False)
   for cmd in ['sign_kernel_file', ifname, ofname + '-sig.bin', 'l', key,
@@ -135,10 +138,38 @@
     p.stdin.write(cmd + '\n')
   p.stdin.close()
   retval = p.wait()
+  os.chdir(olddir)
   if retval:
     raise Exception('%s returned exit code %d' % (signing_tool, retval))
 
 
+def RealSignBolt(hostdir, fname):
+  """Sign the kernel image with the bolt signing tool.
+
+  This uses the broadcom signing tool to sign a kerel for
+  secure boot.  The function expects to be called with the
+  current directory equal to out/build/images.
+
+  Args:
+    hostdir: Absoluate path to buildroot's out/host directory.
+    fname: Name of the image to be signed
+
+  Raises:
+    Exception: if the signing tools fails.
+  """
+
+  tool_path = os.path.join(hostdir, 'usr/bin/boltsigning/gfiber')
+  shutil.copy('signing/gfhd254_private.pem', '/dev/shm/gfhd254_private.pem')
+  shutil.copy(fname, os.path.join(tool_path, 'kernel.img'))
+  exit_code = subprocess.call(
+      ['wine', '../imagetool.exe', '-L', 'kernel', '-O', 'kernel.cfg',
+       '-K', 'signing=true'], cwd=tool_path)
+  subprocess.call(['shred', '-fuz', '/dev/shm/gfhd254_private.pem'])
+  if exit_code:
+    raise Exception('bolt signing tool returned exit code %d' % (exit_code,))
+  shutil.copy(os.path.join(tool_path, 'kernel.img.signed'), fname)
+
+
 def PackVerity(kname, vname, info):
   """Pack verity information in the final image.
 
@@ -185,14 +216,15 @@
              os.path.join(opt.bindir, 'hash.bin'),
              verity_table)
   if opt.sign:
-    olddir = os.getcwd()
-    ifname = os.path.join(opt.bindir, 'signing', opt.kernel)
-    ofname = os.path.join(opt.bindir, opt.kernel)
-    shutil.copy(ofname, ifname)
-    os.chdir(os.path.join(opt.bindir, 'signing'))
-    RealSign(opt.hostdir, 'gfiber_private.pem', ifname, ofname,
-             opt.signing_tool)
-    os.chdir(olddir)
+    if opt.bolt_sign:
+      fname = os.path.join(opt.bindir, opt.kernel)
+      RealSignBolt(opt.hostdir, fname)
+    else:
+      ifname = os.path.join(opt.bindir, 'signing', opt.kernel)
+      ofname = os.path.join(opt.bindir, opt.kernel)
+      shutil.copy(ofname, ifname)
+      RealSign(opt.bindir, opt.hostdir, 'gfiber_private.pem', ifname, ofname,
+               opt.signing_tool)
   else:
     FakeSign(os.path.join(opt.bindir, opt.kernel))
 
diff --git a/wifi/quantenna.py b/wifi/quantenna.py
index 00f818d..7ad4079 100755
--- a/wifi/quantenna.py
+++ b/wifi/quantenna.py
@@ -31,7 +31,7 @@
 
 def _set(mode, opt):
   """Enable wifi."""
-  if opt.band != '5' or not _get_interface() or not _get_qcsapi():
+  if not _get_interface() or not _get_qcsapi():
     return False
 
   _qcsapi('rfenable', '0')
@@ -77,9 +77,9 @@
   return True
 
 
-def _stop(opt):
+def _stop(_):
   """Disable wifi."""
-  if opt.band != '5' or not _get_interface() or not _get_qcsapi():
+  if not _get_interface() or not _get_qcsapi():
     return False
 
   _qcsapi('rfenable', '0')
diff --git a/wifi/quantenna_test.py b/wifi/quantenna_test.py
index 799c2bc..1f99d41 100755
--- a/wifi/quantenna_test.py
+++ b/wifi/quantenna_test.py
@@ -32,21 +32,8 @@
 
 
 @wvtest.wvtest
-def not_5ghz_test():
-  opt = FakeOptDict()
-  opt.band = '2.4'
-  set_fakes()
-  wvtest.WVFAIL(quantenna.set_wifi(opt))
-  wvtest.WVFAIL(quantenna.set_client_wifi(opt))
-  wvtest.WVFAIL(quantenna.stop_ap_wifi(opt))
-  wvtest.WVFAIL(quantenna.stop_client_wifi(opt))
-  wvtest.WVPASSEQ(calls, [])
-
-
-@wvtest.wvtest
 def not_quantenna_test():
   opt = FakeOptDict()
-  opt.band = '5'
   set_fakes(interface='')
   wvtest.WVFAIL(quantenna.set_wifi(opt))
   wvtest.WVFAIL(quantenna.set_client_wifi(opt))
@@ -70,7 +57,6 @@
 @wvtest.wvtest
 def set_wifi_test():
   opt = FakeOptDict()
-  opt.band = '5'
   set_fakes()
 
   # Run set_wifi for the first time.
@@ -158,5 +144,16 @@
   wvtest.WVPASSLT(i[-1], calls.index(['apply_security_config', 'wifi0']))
 
 
+@wvtest.wvtest
+def stop_wifi_test():
+  opt = FakeOptDict()
+  set_fakes()
+  wvtest.WVPASS(quantenna.stop_ap_wifi(opt))
+  wvtest.WVPASS(['rfenable', '0'] in calls)
+  set_fakes()
+  wvtest.WVPASS(quantenna.stop_client_wifi(opt))
+  wvtest.WVPASS(['rfenable', '0'] in calls)
+
+
 if __name__ == '__main__':
   wvtest.wvtest_main()
diff --git a/wifi/wifi.py b/wifi/wifi.py
index 4ed67a5..57ec4cd 100755
--- a/wifi/wifi.py
+++ b/wifi/wifi.py
@@ -220,7 +220,7 @@
   if opt.encryption == 'WEP' or '_PSK_' in opt.encryption:
     psk = os.environ['WIFI_PSK']
 
-  if quantenna.set_wifi(opt):
+  if band == '5' and  quantenna.set_wifi(opt):
     return True
 
   if iw.RUNNABLE_WL() and not iw.RUNNABLE_IW():
@@ -354,7 +354,7 @@
   for band in opt.band.split():
     utils.log('stopping AP for %s GHz...', band)
 
-    if quantenna.stop_ap_wifi(opt):
+    if band == '5' and quantenna.stop_ap_wifi(opt):
       success &= True
       continue
 
@@ -813,7 +813,7 @@
 
   psk = os.environ.get('WIFI_CLIENT_PSK', None)
 
-  if quantenna.set_client_wifi(opt):
+  if band == '5' and quantenna.set_client_wifi(opt):
     return True
 
   phy = iw.find_phy(band, 'auto')
@@ -866,7 +866,7 @@
   for band in opt.band.split():
     utils.log('stopping client for %s GHz...', band)
 
-    if quantenna.stop_client_wifi(opt):
+    if band == '5' and quantenna.stop_client_wifi(opt):
       success &= True
       continue