Category Archives: Programming

Programming

Make HTML Postable in WordPress

In my previous post, I wrote some HTML inside the post that was supposed to be displayed as text, not actually parsed by the browser as HTML. For whatever reason, the <code> tags in WP don’t seem to do their job. Maybe I don’t understand what their job is??

Anyway, I did a little search and was happy to find this little gem that converts all the special browser characters into their text-displayable characters. Very handy!

Postable

Auto-refresh HTML at Given Time

I have a page that grabs data from a database and graphs it using flot. (BTW, If you need dynamic graphs or charts on your website and haven’t checked out flot, do it!) The database is populated by a weather station that aggregates data and records a new entry every 30 minutes. So, every hour at 0 and 30 minutes, new data is recorded and the graphs can be updated.

At first, I did a simple refresh of the page every minute to grab the new data. This works, but is annoying when you have scrolled down and are zooming in on a data set. Every minute, the page reloads and you start over.

I realized I know the exact time new data is available, so why not schedule the page reload on that? It’s not perfectly straightforward, but not really difficult after thinking about it for a few minutes. I’m still using the javascript::timeRefresh, but all I need is a way to set its argument dynamically. I’d explain what the code is doing, but I think you can tell. If not, use Google to look up the PHP functions. The only tricks are the logic on the minutes and setting the seconds parameter in mktime() to zero. PHP’s mktime() is a little magical because it handles the rollover of minutes and days for me. Thanks PHP!

<body onload="JavaScript:timedRefresh(
<?php
$year = date("Y");
$month = date("m");
$date = date("d");
$hour = date("H");
$minute = date("i");
if ($minute < 30)
    $minute = 30;
else
    $minute = 60;
echo 1000 * (mktime($hour,$minute,0,$month,$date, $year) - time());
?>);">

Hide Image Source using CSS Sprite Technique via PHP and Javascript

After thinking how silly it is to attempt to prevent people from downloading images by blocking the right-click functionality, I thought, “There must be a better way to do this!”

So, I came up with a technique to scramble the image and rearrange it using CSS so it looks normal.

I released it to Google Code: http://code.google.com/p/sprhide/

Check it out in action here: http://benburleson.com/sprhide/test.php

Go ahead, try to steal the image!

(Without using a screengrab, jerk!)

It could use a lot of cleaning up and there are plenty of possibilities for improvement.  I’m hoping the Open Source Community will pick it up!

Remote Updates on a Blackfin Device – Part 2

OK, here is the second part of my approach to (safely) apply software application updates remotely to a Blackfin device without using netboot.

See Part 1 for the background.

So, we now have our Blackfin booting uClinux from a compressed image stored in a flash partition.  We allocated two other flash partitions:

  • Bootloader (Das U-Boot)
  • Flash filesystem (jffs2)

In the startup messages, you should see something like this:

Creating 3 MTD partitions on "physmap-flash.0":                                
0x00000000-0x00040000 : "Bootloader"                                           
0x00040000-0x00100000 : "jffs2"                                                
0x00100000-0x00400000 : "uImage"

The jffs2 partition is mounted in the startup script /etc/rc. You need these two lines somewhere:

mkdir /mnt/flash
mount -t jffs2 /dev/mtdblock1 /mnt/flash

The mounted directory /mnt/flash/ is used to store application updates.  Those will persist between device power cycles and are deployed each time the device boots.

The application deployment is kicked off by another line in /etc/rc.  I simply call a script I created: /bin/deploy.  Here’s what is inside /bin/deploy:

#!/bin/sh                                                                      

cd /mnt/flash                                                                  

machine=`hostname`                                                             
pkgname="$machine-*.tgz"                                                       
md5name="$machine-*.md5"                                                       

md5sum -c $md5name                                                             
if [ $? -ne 0 ]                                                                
then                                                                           
  echo "md5 BAD! Deploy aborted."                                              
else                                                                           
  echo "md5 OK. Deploying applications."                                       
  tar zxvf $pkgname -C /                                                       
fi

This script changes to the directory /mnt/flash/ (our persistant flash filesystem) and checks if a valid tarball exists for this device.  The tarball must begin with the hostname of the device and includes a version id.  The tarball must also pass an md5 check.  If the check is successful, the tarball is exploded from / (root), placing new software in the device.

Now, how do we get the tarball of updated software and its md5 into /mnt/flash?  I created another script for that:

#!/bin/sh

if [ $# -ne 1 ]
then
  echo "Syntax Error"
  echo "Usage $0 <version>  e.g. $0 1.0.2"
else

  cd /mnt/flash

  machine=`hostname`
  pkgname="$machine-$1.tgz"
  md5name="$machine-$1.md5"

  if [ -f $pkgname ]
  then
    echo "$pkgname already exists.  Download new copy? [Y/n]"
    read ans
    if [ $ans == "N" -o $ans == "n" ]
    then
      echo "Using local copy of $pkgname."
      download=0
    else
      echo "Downloading new copy of $pkgname."
      download=1
    fi
  else
    echo "$pkgname needs to be downloaded."
    download=1
  fi

  if [ $download -eq 1 ]
  then
    rm $machine-*.tgz
    rm $machine-*.md5
    tftp -g -l $pkgname -r $pkgname fs
    tftp -g -l $md5name -r $md5name fs
    md5sum -c $md5name
  fi
  /bin/deploy
fi

This script is just a smart downloader.  It takes an input parameter as the version number of the device application upgrade to download.  It prepends the hostname to the version number and creates two filenames: 1) the tarball, and 2) the md5.

It first checks if the upgrade needs to be downloaded and allows the user a choice to download a new copy or use existing one if upgrade version exists.  It it does not exist, it automatically downloads it (via TFTP) from a TFTP server.  (The setup of that server is outside of the scope of this, but I will explain below how the tarball and md5 are created.)

After the download of the upgrade, it performs an md5 check and deploys the new upgrade.

The final step is creating the upgrade tarball and md5.  To accomplish this, I created a slightly crude ant task:

tar czvf $(LCO_VER_FW).tgz -C romfs/ bin/lco-fw-post bin/lco-enviro-update home/httpd/cgi-bin/command home/httpd/cgi-bin/status
md5sum $(LCO_VER_FW).tgz > $(LCO_VER_FW).md5
scp $(LCO_VER_FW).* root@fs:/tftpboot/

It contains three steps:

  • Create tarball – based from root dir (romfs), include necessary files
  • Create md5
  • scp both files to TFTP server

LCO_VER_FW is just a variable conatining the hostname and version id.

And there you have it!  A complete, safe solution to upgrade device-specific software remotely without using netboot!

Remote Updates on a Blackfin Device – Part 1

Background

The goal is a controller for various mechanical devices (move motors, read sensors via GPIO) with a web interface (HTML and web-services).

I spent some time organizing a safe method for deploying application updates to a remote blackfin device.  There were a couple restrictions that led to my final plan.

  • If the update process fails, the device should still boot and be accessible via internet.
  • Updating needs to be done remotely via internet.

Approach

Flash Layout

Three paritions:

  • Bootloader (u-boot) – 2 sectors 0x20000000-0x2003FFFF
  • Flash filesystem (jffs2) – 6 sectors 0x20040000-0x200FFFFF
  • uClinux compressed image (uImage) – 24 sectors 0x20100000-0x203FFFFF

I originally placed the uImage parition directly after the u-boot partition, with the jffs2 partition at the end.  The flash device on the CM-BF537E splits the flash into two halves addressable by toggling a GPIO pin (pf4).  Some tools handled the addressing and toggling of pf4 for me, others didn’t.  It turned out easier to move the jffs2 parition into the first half of flash and let the uImage parition straddle the flash halves.

Setting Up U-Boot

On the first boot, I wanted u-boot to download the uImage (via TFTP) and write it to flash memory.  However, we did not want the device to always netboot, so u-boot would then alter itself to boot from the flashed uImage.

U-boot also needs to erase the jffs2 paritions on a fresh CM-BF537E so the filesystem can mount.

Here is the important section from cm-bf537e.h

"erasejffs2="
    "protect off 0x20040000 0x200FFFFF;"
    "erase 0x20040000 0x200FFFFF;"
    "protect on 0x20040000 0x200FFFFF;"
    ""
"tftpupdate="
    "run erasejffs2;"
    "tftp $(loadaddr) $(imagename);"
    "protect off 0x20100000 0x203FFFFF;"
    "erase 0x20100000 0x203FFFFF;"
    "cp.b $(loadaddr) 0x20100000 0x300000;"
    "protect on 0x20100000 0x203FFFFF;"
    "setenv bootcmd run localboot;"
    "saveenv;"
    "reset"
    ""
"localboot="
    "ping 172.16.5.1;"
    "pf4 set;"
    "cp.b 0x20100000 $(loadaddr) 100000;"
    "pf4 clear;"
    "cp.b 0x20000000 0x1100000 200000;"
    "pf4 set;"
    "bootm"
    ""

Again, on first boot, the device auto-runs tftpupdate.  Here is what happens:

  • Jffs2 parition is erased
  • uImage is downloaded into memory (address 0x1000000)
  • Unprotect flash sectors where uImage will be stored
  • Erase flash sectors where uImage will be stored
  • Copy uImage into flash
  • Protect flash sectors where uImage is now stored
  • Change default startup command to localboot (described below)
  • Save setting change
  • Reset device

When the device comes back up, here is what happens:

  • Ping a server (the only thing this does is write the u-boot MAC Address to the network device so uClinux will use the same MAC Address and not assign a random one)
  • Set the GPIO pin to use the first half of flash (mentioned above)
  • Copy uImage from first half of flash into memory (0x1000000)
  • Clear GPIO pin to use second half of flash
  • Copy remainder of uImage in upper half of flash to memory (offset from previous copy)
  • Re-set GPIO pin
  • Boot uImage from memory

From here, the device is now running!

Upgrades to the uImage stored in flash are possible, but the u-boot console is needed to halt the autoboot and run the tftpupdate macro again.

This post is actually just the setup of U-Boot and uClinux to boot a blackfin device from a stored uImage (i.e. NOT netboot).  Part 2 will explain the scheme for updating the device remotely – without netboot!