Bar
SpaceWire UK
Specialist providers of VHDL Intellectual Property & Design Services
BarBarBarBar
Tutorial
Missing Image!
Part 18 - Add LAMP (Linux-Apache-MySQL-PHP) style stack to PetaLinux (9 August 2023)

Introduction

This tutorial details the steps required to install a LAMP style stack on PetaLinux. The previously installed busybox-httpd is OK but not quite as flexible as the likes of say Apache. The stack to be installed shall consist of Apache2, SQLite3 & PHP7, and for good measure phpLiteAdmin. The latter offers a graphical interface for SQL databases much the same as myPHPAdmin.

Aims

The aims of this tutorial are as follows :-

    Part 1 - Project Setup

    1. Setup environment
    2. Obtain tutorial files from Bitbucket (optional)

    Part 2 - OS Development

    1. Change present working directory
    2. Bump Version
    3. Disable busybox-httpd webserver
    4. Configure PetaLinux for LAMP
    5. Build & package PetaLinux

    Part 4 - Hardware Deployment

    1. Setup Zedboard hardware
    2. Launch MiniCom terminal emulator
    3. Deploy firmware & software on Zedboard
    4. Check boot is working as expected

    Part 5 - Configure & validate LAMP style setup

    1. Check PetaLinux boot
    2. Check HTML
    3. Check CGI shell scripts
    4. Check PHP
    5. Check SQLite
    6. Check phpLiteAdmin
    7. Migration
    8. Make changes permanent
    9. Build & package PetaLinux
    10. Deploy firmware & software on Zedboard
    11. Check everything is working as expected

    Part 6 - Revision Control

    1. Commit new & updated files
    2. Final checks
    #### Part 1 - Project Setup ####

    1. Setup environment

    Setup Xilinx design environment for the 2021.2 toolset.
    steve@Desktop:~$ xilinx
    Xilinx tools available tools at /opt/Xilinx :-
    1) 2021.2 - Vivado - SDK - Vitis - PetaLinux
    0) Exit
    Please select tools required or exit : 1

    Tools are as follows :-
    vivado @ /opt/Xilinx/Vivado/2021.2/bin/vivado
    vitis @ /opt/Xilinx/Vitis/2021.2/bin/vitis
    petalinux-build @ /opt/Xilinx/PetaLinux/2021.2/tool/tools/common/petalinux/bin/petalinux-build

    2. Obtain tutorial files from Bitbucket (optional)

    Starting from this point, having not followed the previous tutorials, can be achieved by obtaining the required files from BitBucket. The only prerequisite is that Part 1 - Installation of tools, setup of environment and creation of project area as been completed.

    Obtain OS source.
    steve@Desktop:~$ cd ~/projects
    steve@Desktop:~/projects$ git clone -b v11.0 https://bitbucket.org/spacewire_firmware/zedboard_linux
    #### Part 2 - OS Development ####

    3. Change present working directory

    Change the present working directory to be the project directory.
    steve@Desktop:~$ cd ~/projects/zedboard_linux/os/petalinux

    4. Bump Version

    Change the version (or revision) number for this new development, this prevents ghost (post-release, same version) builds from appearing.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ sed -i 's/11.0/12.0/g' project-spec/meta-user/recipes-apps/website/files/project.txt

    5. Disable busybox-httpd webserver

    Launch the PetaLinux configuration tool.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ petalinux-config -c rootfs
    Navigate the menu selecting Filesystem Packages » base » busybox, disable busybox-httpd and then save the configuration and exit the tool. Missing Image!

    6. Configure PetaLinux for LAMP

    Configure PetaLinux to use Apache, SQLite & Apache's PHP Module. For good measure also add the nano text editor.

    Edit the petalinuxbsp.conf as shown below.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl project-spec/meta-user/conf/petalinuxbsp.conf

    petalinuxbsp.conf

    1. #User Configuration

    2. #OE_TERMINAL = "tmux"

    3. IMAGE_INSTALL_append = " ntp ntpdate ntpq sntp nano"
    4. PACKAGECONFIG_append_pn-php = " apache2"
    5. IMAGE_INSTALL_append = " apache2 sqlite3 php-modphp"

    7. Build & package PetaLinux

    Rebuild PetaLinux to include the updates and package it ready for deployment.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ petalinux-build
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ petalinux-package --prebuilt --force
    #### Part 4 - Hardware Deployment ####

    8. Setup Zedboard hardware

    If not already, connect up the hardware as follows :-
    1. Xubuntu PC USB ⇄ Zedboard USB JTAG/Debug
    2. Xubuntu PC USB ⇄ Zedboard USB UART
    3. Zedboard Ethernet ⇄ Router
    4. Xubuntu PC Ethenet ⇄ Router
    5. Router ⇄ Internet
    Missing Image! Set the boot mode jumpers on the Zedboard for JTAG. Missing Image! Power on the Zedboard.

    9. Launch MiniCom terminal emulator

    If not already running, open up a new terminal and launch the MiniCom terminal emulator.
    steve@Desktop:~$ minized

    Welcome to minicom 2.7.1

    OPTIONS: I18n
    Compiled on Dec 23 2019, 02:06:26.
    Port /dev/ttyACM0, 06:34:25

    Press CTRL-A Z for help on special keys

    10. Deploy firmware & software on Zedboard

    Deploy PetaLinux to the Zedboard via JTAG.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ petalinux-boot --jtag --prebuilt 3

    11. Check boot is working as expected

    All being well the following sequence of events should be observed.
    1. The blue done LED illuminates indicating the Programmable Logic (PL) has been programmed.
    2. The software runs on the Processor System (PS).
    3. PetaLinux starts to boot.
    4. The led-runner application launches and executes the expanding & contracting LED illumination sequence.
    5. The PetaLinux login prompt appears in the terminal emulator.
    #### Part 5 - Configure & validate LAMP style setup ####

    12. Check PetaLinux boot

    The MiniCom terminal emulator displays the following error message due to a missing file.
    Starting web server: apache2cat: can't open '/run/httpd.pid': No such file or directory
    It also displays the help page for grep, most probably due to bad options usage on the call.

    13. Check HTML

    Access the webserver on the Zedboard by pointing a browser at its IP address 192.168.2.87.

    All being well the following page should be displayed. Missing Image! Login to PetaLinux using the root credentials (username = root & password = root).

    Examine Apache's configuration file.
    root@petalinux:~# nano /etc/apache2/httpd.conf
    Search for DocumentRoot (press Ctrl + W to search, enter DocumentRoot and then press Enter).

    As can be seen, HTML is being served from /usr/share/apache2/default-site/htdocs.

    Quite Nano (press Ctrl + X).

    Examine the htdocs directory and the files it contains.
    root@petalinux:~# ls -la /usr/share/apache2/default-site/htdocs
    total 4
    drwxr-xr-x    3 root     root            80 Mar  9  2018 .
    drwxr-xr-x    3 root     root            60 Mar  9  2018 ..
    -rw-r--r--    1 root     root            45 Mar  9  2018 index.html
    drwxr-xr-x   14 root     root          4100 Mar  9  2018 manual
    The HTML file being served is index.html, examine the file.
    root@petalinux:~# cat /usr/share/apache2/default-site/htdocs/index.html

    index.html

    1. <html><body><h1>It works!</h1></body></html>
    The HTML service is working OK.

    14. Check CGI shell scripts

    Examine Apache's configuration file again to see what the CGI arrangements are.
    root@petalinux:~# nano /etc/apache2/httpd.conf
    Search for cgi-bin. Do this multiple times to find the two lines of interest.

    As can be seen, CGI is being served from /usr/libexec/apache2/modules/cgi-bin.

    Quite Nano.

    Examine the cgi-bin directory and the files it contains.
    root@petalinux:~# ls -la /usr/libexec/apache2/modules/cgi-bin
    total 16
    drwxr-xr-x    2 root     root           120 Mar  9  2018 .
    drwxr-xr-x    3 root     root          1900 Mar  9  2018 ..
    -rw-r--r--    1 root     root           820 Mar  9  2018 printenv
    -rw-r--r--    1 root     root          1074 Mar  9  2018 printenv.vbs
    -rw-r--r--    1 root     root          1133 Mar  9  2018 printenv.wsf
    -rw-r--r--    1 root     root          1261 Mar  9  2018 test-cgi
    Examine the CGI script test-cgi.
    root@petalinux:~# cat /usr/libexec/apache2/modules/cgi-bin/test-cgi

    test-cgi

    1. #

    2. # To permit this cgi, replace # on the first line above with the
    3. # appropriate #!/path/to/sh shebang, and set this script executable
    4. # with chmod 755.
    5. #
    6. # ***** !!! WARNING !!! *****
    7. # This script echoes the server environment variables and therefore
    8. # leaks information - so NEVER use it in a live server environment!
    9. # It is provided only for testing purpose.
    10. # Also note that it is subject to cross site scripting attacks on
    11. # MS IE and any other browser which fails to honor RFC2616.

    12. # disable filename globbing
    13. set -f

    14. echo "Content-type: text/plain; charset=iso-8859-1"
    15. echo

    16. echo CGI/1.0 test script report:
    17. echo

    18. echo argc is $#. argv is "$*".
    19. echo

    20. echo SERVER_SOFTWARE = $SERVER_SOFTWARE
    21. echo SERVER_NAME = $SERVER_NAME
    22. echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
    23. echo SERVER_PROTOCOL = $SERVER_PROTOCOL
    24. echo SERVER_PORT = $SERVER_PORT
    25. echo REQUEST_METHOD = $REQUEST_METHOD
    26. echo HTTP_ACCEPT = "$HTTP_ACCEPT"
    27. echo PATH_INFO = "$PATH_INFO"
    28. echo PATH_TRANSLATED = "$PATH_TRANSLATED"
    29. echo SCRIPT_NAME = "$SCRIPT_NAME"
    30. echo QUERY_STRING = "$QUERY_STRING"
    31. echo REMOTE_HOST = $REMOTE_HOST
    32. echo REMOTE_ADDR = $REMOTE_ADDR
    33. echo REMOTE_USER = $REMOTE_USER
    34. echo AUTH_TYPE = $AUTH_TYPE
    35. echo CONTENT_TYPE = $CONTENT_TYPE
    36. echo CONTENT_LENGTH = $CONTENT_LENGTH
    Edit the file as the header comment suggests, replace the first line # with #!/bin/sh
    root@petalinux:~# nano /usr/libexec/apache2/modules/cgi-bin/test-cgi
    Quit Nano (press Ctrl + X to quit, enter y when asked about saving the modified buffer, then Enter to confirm the original file location).

    Access the webserver by pointing a browser at http://192.168.2.87/cgi-bin/test-cgi.

    Sadly the test-cgi script is not being executed, instead its contents are simply being dumped to the browser. Missing Image! Take a look at Apache's configuration file again.
    root@petalinux:~# nano /etc/apache2/httpd.conf
    Search for mod_cgid.so.

    As can be seen, the LoadModule for this line is commented out. Delete the # at the start of the line and save the file.

    Reload Apache so the updated httpd.conf is being used.
    root@petalinux:~# /etc/init.d/apache2 reload
    Access the webserver again by pointing a browser at 192.168.2.87/cgi-bin/test-cgi.

    Sadly the test-cgi script is still not being executed. Missing Image! Thinking back to the previous Webserver tutorial, the BitBake recipe set execute permissions on the shell script CGI's.

    As seen above, the permissions for test-cgi are -rw-r--r--. Change these so the file is executable.
    root@petalinux:~# chmod +x /usr/libexec/apache2/modules/cgi-bin/test-cgi
    Access the webserver again by pointing at http://192.168.2.87/cgi-bin/test-cgi.

    All being well the following page should be displayed. Missing Image! The CGI (shell script) service is working OK.

    15. Check PHP

    Perform a quick search for any pre-installed PHP files that may be of use.
    root@petalinux:~# find / -name "*.php"
    None found! Create the classic Hello World example using basic HTML & PHP.
    root@petalinux:~# nano /usr/libexec/apache2/modules/cgi-bin/hello_world.php

    hello_world.php

    1. <html>
    2. <head>
    3. <title>PHP Test</title>
    4. </head>
    5. <body>
    6. <?php echo '<p>Hello World</p>'; ?>
    7. </body>
    8. </html>

    Note that PHP files do not need to be executable as they are interpreted by Apache and not executed.

    Access the webserver again by pointing at http://192.168.2.87/cgi-bin/hello_world.php.

    All being well the following page should be displayed. Missing Image! Do a quick and dirty The CGI (PHP) service is working OK.

    16. Check SQLite

    Note that Apache is run using the daemon account, the old busybox-httpd used the root account. Due to this care must be taken with file & directory permissions such that correct access can be obtained.

    As seen above, the permissions for cgi-bin are drwxr-xr-x and the directory is owned by root. Creating a database in this directory via a PHP page will not be possible without changing the permissions first. Instead create a db directory with full access.
    root@petalinux:~# mkdir /usr/libexec/apache2/modules/cgi-bin/db
    root@petalinux:~# chmod 777 /usr/libexec/apache2/modules/cgi-bin/db
    Create a very simple HTML, PHP & SQLite test page that creates/opens a database, creates a table, inserts a row inside the table and closes the database.
    root@petalinux:~# nano /usr/libexec/apache2/modules/cgi-bin/sqlite_test.php

    sqlite_test.php

    1. <?php
    2. //
    3. // File .......... sqlite_test.php
    4. // Author ........ Steve Haywood
    5. // Version ....... 1.0
    6. // Date .......... 3 August 2023
    7. // Description ...
    8. //   Simple HTML, PHP & SQLite example code that checks the basic operation of
    9. // SQLite. SQL queries used are :-
    10. //
    11. // 1. Create/open database
    12. // 1. Create table
    13. // 3. Insert row
    14. // 4. Close database
    15. //
    16. ?>

    17. <!DOCTYPE html>
    18. <html lang="en">
    19. <head>
    20. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    21. <title>SQLite Test</title>
    22. </head>

    23. <?php

    24. class MyDB extends SQLite3 {
    25.   function __construct() {
    26.     $this->open('db/test.db');
    27.   }
    28. }

    29. echo 'Creating/opening database<br>';
    30. $db = new MyDB();
    31. if ($db) {
    32.   echo 'Success';
    33. } else {
    34.   echo 'Failure : ' . $db->lastErrorMsg();
    35. }
    36. echo '<br><br>';

    37. echo 'Creating table<br>';
    38. $return = $db->exec("CREATE TABLE fruit (item VARCHAR(30) NOT NULL PRIMARY KEY UNIQUE, quantity int unsigned NOT NULL)");
    39. if ($return) {
    40.   echo 'Success';
    41. } else {
    42.   echo 'Failure : ' . $db->lastErrorMsg();
    43. }
    44. echo '<br><br>';

    45. echo 'Inserting 1st row in table<br>';
    46. $result = $db->exec("INSERT INTO fruit (item, quantity) VALUES ('Apple', '5')");
    47. if ($result) {
    48.   echo 'Success';
    49. } else {
    50.   echo 'Failure : ' . $db->lastErrorMsg();
    51. }
    52. echo '<br><br>';

    53. echo 'Inserting 2nd row in table<br>';
    54. $result = $db->exec("INSERT INTO fruit (item, quantity) VALUES ('Orange', '12')");
    55. if ($result) {
    56.   echo 'Success';
    57. } else {
    58.   echo 'Failure : ' . $db->lastErrorMsg();
    59. }
    60. echo '<br><br>';

    61. echo 'Closing database<br>';
    62. $result = $db->close();
    63. if ($result) {
    64.   echo 'Success';
    65. } else {
    66.   echo 'Failure : ' . $db->lastErrorMsg();
    67. }

    68. ?>

    69. </body>
    70. </html>

    Access the webserver again by pointing at http://192.168.2.87/cgi-bin/sqlite_test.php.

    All being well the following page should be displayed. Missing Image! The SQLite service is working OK.

    17. Check phpLiteAdmin

    phpLiteAdmin is not an installable option on PetaLinux so it must be installed manually. Fortunately this only consists of two PHP files.

    Download the latest Stable version of phpLiteAdmin into ~/Downloads.

    Extract the files from the archive.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ unzip ~/Downloads/phpLiteAdmin_v*.zip -d /tmp
    Archive:  ~/Downloads/phpLiteAdmin_v1-9-8-2.zip
      inflating: /tmp/phpliteadmin.config.sample.php
      inflating: /tmp/phpliteadmin.php
      inflating: /tmp/readme.md
    Edit the configuration file to change the database location. Change the line $directory = '.'; to $directory = 'db';
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl /tmp/phpliteadmin.config.sample.php
    Copy the two PHP files to PetaLinux for testing (rename the configuration file).
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ scp /tmp/phpliteadmin.php root@192.168.2.87:/usr/libexec/apache2/modules/cgi-bin
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ scp /tmp/phpliteadmin.config.sample.php root@192.168.2.87:/usr/libexec/apache2/modules/cgi-bin/phpliteadmin.config.php
    Access the webserver again by pointing at http://192.168.2.87/cgi-bin/phpliteadmin.php.

    All being well the following page should be displayed. Missing Image! Log in using the password admin to hopefully reveal the cockpit page.

    The database test.db as created by sqlite_test.php should be should down the left-hand side of the page. View and edit the database by clicking on the links and entering SQL queries. Missing Image! The phpLiteAdmin service is working OK.

    18. Migration

    At this point the directory structure being used is that of Apache. There are two options moving forward :-
    1. The files from /srv/www & /srv/www/cgi-bin can be migrated to /usr/share/apache2/default-site/htdocs & /usr/libexec/apache2/modules/cgi-bin respectively.
    2. The Apache configuration file (httpd.conf) can be modified to use /srv/www & /srv/www/cgi-bin.
    The Apache configuration file as already been edited to enable CGI shell script execution, which will need to become sticky, i.e. part of the PetaLinux build process. It makes sense to go with option 2.

    Take a look at Apache's configuration file again.
    root@petalinux:~# nano /etc/apache2/httpd.conf
    Use the replace text command in Nano (Ctrl + \) to make the following changes to lines 221, 222, 338 & 354. Save the file and reload Apache so the updates take effect.
    root@petalinux:~# /etc/init.d/apache2 reload
    All being well accessing the webserver should look like it did prior to all the changes made in this tutorial.

    Check the following pages to confirm :- For the latter change the Address in the Peek/Poke table from 0x41200000 to 0x40010000 (the LED register).

    Attempt to Peek & Poke this register. The two operations should fail with the error message Failed to open /dev/mem.

    Note again that Apache is run using the daemon account, the old busybox-httpd used the root account. To access /dev/mem requires root privileges, hence the failures.

    Files can be executed using root privileges by non-root users by adding the s attribute (not recommended). Execute the following command to set root execution privileges on the three files of concern.
    root@petalinux:~# chmod a+s /srv/www/cgi-bin/{peek,poke,peekstring}
    Attempt to Peek & Poke the register again, this time the operations should work as expected. The Firmware Information should also now display upon pressing the Read ID button.

    Check all the modifications made in /usr/libexec/apache2/modules/cgi-bin work /srv/www/cgi by simply moving the related files.
    root@petalinux:~# mv /usr/libexec/apache2/modules/cgi-bin/{db,test-cgi,*.php} /srv/www/cgi-bin
    Check the following pages to confirm :-

    19. Make changes permanent

    To make the changes to PetaLinux permanent they need to be included in the build process.

    Copy the files into place.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ scp root@192.168.2.87:/srv/www/cgi-bin/test-cgi ~/projects/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ scp root@192.168.2.87:/srv/www/cgi-bin/*.php ~/projects/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin
    Apply a slight modification to the uptime.cgi call inside uptime.js - Add a / before cgi-bin on line 73. This is now the same as the calls to peek, poke & peekstring.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl ~/projects/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/uptime.js
    Do a quick & dirty conversion of index.sh (shell script) into index.php (PHP).
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ cp ~/projects/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin/index.cgi ~/projects/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin/index.php
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl ~/projects/zedboard_linux/os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin/index.php

    index.php

    1. <?php
    2. // Get information
    3. $sys_host = exec('hostname', $retval);
    4. $sys_time = exec('date', $retval);
    5. $sys_load = exec('awk \'{print $1}\' /proc/loadavg', $retval);
    6. $sys_up = exec('awk \'{print $1}\' /proc/uptime', $retval);
    7. $cpu_model = exec('grep model /proc/cpuinfo | cut -d : -f2 | tail -1 | sed \'s/\s//\'', $retval);
    8. $cpu_cores = exec('grep -c ^processor /proc/cpuinfo', $retval);
    9. $mem_total = exec('free -m | awk \'NR==2{print $2}\'', $retval);
    10. $mem_used = exec('free -m | awk \'NR==2{print $3}\'', $retval);
    11. $mem_free = exec('free -m | awk \'NR==2{print $4}\'', $retval);
    12. $net_mac = exec('cat /sys/class/net/eth0/address', $retval);
    13. $net_ip_loc = exec('ip a | grep inet | grep -vw lo | grep -v inet6 | cut -d \/ -f1 | sed \'s/[^0-9\.]*//g\'', $retval);
    14. $net_ip_ext = exec('wget -q -O- http://ipecho.net/plain', $retval);
    15. ?>

    16. <!DOCTYPE html>
    17. <html lang="en">
    18. <head>
    19. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    20. <link href="../styles.css" rel="stylesheet">
    21. <title>Zedboard Webserver</title>
    22. </head>
    23. <body onload="add_register()">

    24. <div class="section"><h2>Zedboard Webserver</h2></div>

    25. <div class="section">
    26. <table>
    27. <thead>
    28. <tr><th colspan="3">Operating System Information <button onclick="read_os_ids()">Read ID</button></th>
    29. </tr>
    30. </thead>
    31. <tbody>
    32. <tr>
    33. <td style="text-align:right">Description :</td>
    34. <td style="text-align:left" id="oid_0">Unknown</td>
    35. <td><img id="osid_0" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    36. </tr>
    37. <tr>
    38. <td style="text-align:right">Company :</td>
    39. <td style="text-align:left" id="oid_1">Unknown</td>
    40. <td><img id="osid_1" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    41. </tr>
    42. <tr>
    43. <td style="text-align:right">Author :</td>
    44. <td style="text-align:left" id="oid_2">Unknown</td>
    45. <td><img id="osid_2" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    46. </tr>
    47. <tr>
    48. <td style="text-align:right">Version :</td>
    49. <td style="text-align:left" id="oid_3">Unknown</td>
    50. <td><img id="osid_3" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    51. </tr>
    52. <tr>
    53. <td style="text-align:right">Timestamp :</td>
    54. <td style="text-align:left" id="oid_4">Unknown</td>
    55. <td><img id="osid_4" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    56. </tr>
    57. <tr>
    58. <td style="text-align:right">Hash :</td>
    59. <td style="text-align:left" id="oid_5">Unknown</td>
    60. <td><img id="osid_5" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    61. </tr>
    62. </tbody>
    63. </table>
    64. <table>
    65. <thead>
    66. <tr><th colspan="3">Firmware Information <input type="submit" value="Read ID" id="read_ids" onclick="read_ids()"></th>
    67. </tr>
    68. </thead>
    69. <tbody>
    70. <tr>
    71. <td style="text-align:right">Description :</td>
    72. <td style="text-align:left" id="id_0">Unknown</td>
    73. <td><img id="sid_0" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    74. </tr>
    75. <tr>
    76. <td style="text-align:right">Company :</td>
    77. <td style="text-align:left" id="id_1">Unknown</td>
    78. <td><img id="sid_1" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    79. </tr>
    80. <tr>
    81. <td style="text-align:right">Author :</td>
    82. <td style="text-align:left" id="id_2">Unknown</td>
    83. <td><img id="sid_2" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    84. </tr>
    85. <tr>
    86. <td style="text-align:right">Version :</td>
    87. <td style="text-align:left" id="id_3">Unknown</td>
    88. <td><img id="sid_3" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    89. </tr>
    90. <tr>
    91. <td style="text-align:right">Timestamp :</td>
    92. <td style="text-align:left" id="id_4">Unknown</td>
    93. <td><img id="sid_4" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    94. </tr>
    95. <tr>
    96. <td style="text-align:right">Hash :</td>
    97. <td style="text-align:left" id="id_5">Unknown</td>
    98. <td><img id="sid_5" style="vertical-align:middle" src="../amber.gif" title="Unknown!" alt="Missing Image!"></td>
    99. </tr>
    100. </tbody>
    101. </table>
    102. </div>

    103. <div class="section"><img src="../zedboard.png" alt="Missing Image!"></div>

    104. <div class="section">

    105. <table>
    106. <tr><th colspan="2">System</th></tr>
    107. <tr><td>Hostname</td>
    108. <td><?php echo $sys_host ?></td>
    109. </tr><tr><td>Time</td><td><?php echo $sys_time ?></td></tr>
    110. <tr><td>Uptime</td><td><span id="uptime_text"><?php echo $sys_up ?></span> seconds <button onclick="get_uptime()">Refresh</button> Auto :
    111. <select id="uptime" onchange="uptime();">
    112.   <option value="0">Off</option>
    113.   <option value="1">1s</option>
    114.   <option value="5">5s</option>
    115. </select>
    116. </td></tr>
    117. </table>

    118. <table>
    119. <tr><th colspan="2">CPU</th></tr>
    120. <tr><td>Model</td>
    121. <td><?php echo $cpu_model ?></td></tr>
    122. <tr><td>Cores</td><td><?php echo $cpu_cores ?></td></tr>
    123. <tr><td>Load</td><td><?php echo $sys_load ?></td></tr>
    124. </table>

    125. <table>
    126. <tr><th colspan="2">Memory</th></tr>
    127. <tr><td>Total</td><td><?php echo $mem_total ?> Mb</td></tr>
    128. <tr><td>Used</td><td><?php echo $mem_used ?> Mb</td></tr>
    129. <tr><td>Free</td><td><?php echo $mem_free ?> Mb</td></tr>
    130. </table>

    131. <table>
    132. <tr><th colspan="2">Network</th></tr>
    133. <tr><td>MAC Address</td><td><?php echo $net_mac ?></td></tr>
    134. <tr><td>Internal IP</td><td><?php echo $net_ip_loc ?></td></tr>
    135. <tr><td>External IP</td><td><?php echo $net_ip_ext ?></td></tr>
    136. </table>

    137. </div>

    138. <div class="section">
    139. <table id="registers">
    140. <tr>
    141. <th>Address</th>
    142. <th>Peek Value</th>
    143. <th>Sel</th>
    144. <th>Peek</th>
    145. <th>Status</th>
    146. <th>Copy</th>
    147. <th>Poke Value</th>
    148. <th>Sel</th>
    149. <th>Poke</th>
    150. <th>Status</th>
    151. <th>Description</th>
    152. </tr>
    153. </table>
    154. <br><br>
    155. <input title="Add new row to end of address table" type="button" value="Add" onclick="add_row()">
    156. <select title="Set type of row to add to address table" id="type">
    157.   <option value="0">Register</option>
    158.   <option value="1">Section</option>
    159. </select>
    160. <input title="Remove last address from table" type="button" value="Remove" onclick="rem_register()">
    161. <input title="Peek all selected addresses in table" type="button" value="Peek All" onclick="peek_all()">
    162. <input title="Copy all table peek values into poke values" type="button" value="Copy All" onclick="copy_all()">
    163. <input title="Poke all selected addresses in table" type="button" value="Poke All" onclick="poke_all()">
    164. Peek Refresh :
    165. <select title="Set timer interval for automatic peek of table addresses" id="timer" onchange="timer()">
    166.   <option value="0">Off</option>
    167.   <option value="1">1s</option>
    168.   <option value="5">5s</option>
    169. </select>
    170. Number Format :
    171. <select title="Set number format for peek and poke values" id="format" onchange="format()">
    172.   <option value="0">Hexadecimal</option>
    173.   <option value="1">Unsigned</option>
    174. </select>
    175. Configuration :
    176. <button title="Create configuration file from table" onclick="create_config()">Create...</button> <a title="Right click and Save Link As... to locate and rename this file" download="config.txt" id="download" href="" style="display: none">config.txt</a>
    177. <input title="Read configuration file into table" type="file" id="load_config">
    178. </div>

    179. <div class="section">Designed by Steve Haywood @ 2021</div>

    180. <script src="../uptime.js"></script>

    181. </body>
    182. </html>

    Modify index.html such that it becomes an index page for accessing all the other pages.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl project-spec/meta-user/recipes-apps/website/files/index.html

    index.html

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    5. <title>Zedboard webserver</title>
    6. </head>
    7. <body>
    8. <h3>Index</h3>
    9. <ul>
    10. <li><a href="cgi-bin/test-cgi" target=_blank>cgi-bin/test-cgi</a></li>
    11. <li><a href="cgi-bin/hello_world.php" target=_blank>cgi-bin/hello_world.php</a></li>
    12. <li><a href="cgi-bin/sqlite_test.php" target=_blank>cgi-bin/sqlite_test.php</a></li>
    13. <li><a href="cgi-bin/phpliteadmin.php" target=_blank>cgi-bin/phpliteadmin.php</a></li>
    14. <li><a href="cgi-bin/index.php" target=_blank>cgi-bin/index.php</a></li>
    15. </ul>
    16. </body>
    17. </html>

    Modify the website BitBake recipe to install the new & modified files.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl project-spec/meta-user/recipes-apps/website/website.bb

    website.bb

    1. #
    2. # This file is the website recipe.
    3. #

    4. SUMMARY = "Simple website application"
    5. SECTION = "PETALINUX/apps"
    6. LICENSE = "MIT"
    7. LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

    8. SRC_URI = "file://index.html"
    9. SRC_URI += "file://uptime.js"
    10. SRC_URI += "file://zedboard.png"
    11. SRC_URI += "file://styles.css"
    12. SRC_URI += "file://cgi-bin/index.php"
    13. SRC_URI += "file://cgi-bin/uptime.cgi"
    14. SRC_URI += "file://cgi-bin/test-cgi"
    15. SRC_URI += "file://cgi-bin/hello_world.php"
    16. SRC_URI += "file://cgi-bin/sqlite_test.php"
    17. SRC_URI += "file://cgi-bin/phpliteadmin.php"
    18. SRC_URI += "file://cgi-bin/phpliteadmin.config.php"
    19. SRC_URI += "file://amber.gif"
    20. SRC_URI += "file://green.gif"
    21. SRC_URI += "file://red.gif"
    22. SRC_URI += "file://project.txt"

    23. FILES_${PN} += "/srv/www"

    24. S = "${WORKDIR}"

    25. do_install() {
    26.      install -d ${D}/srv/www
    27.      install -m 0644 ${S}/index.html ${D}/srv/www/index.html
    28.      install -m 0644 ${S}/uptime.js ${D}/srv/www
    29.      install -m 0644 ${S}/zedboard.png ${D}/srv/www
    30.      install -m 0644 ${S}/styles.css ${D}/srv/www
    31.      install -m 0644 ${S}/amber.gif ${D}/srv/www
    32.      install -m 0644 ${S}/green.gif ${D}/srv/www
    33.      install -m 0644 ${S}/red.gif ${D}/srv/www
    34.      install -m 0644 ${S}/project.txt ${D}/srv/www
    35.      install -d ${D}/srv/www/cgi-bin
    36.      install -m 0777 -d ${D}/srv/www/cgi-bin/db
    37.      install -m 0644 ${S}/cgi-bin/index.php ${D}/srv/www/cgi-bin
    38.      install -m 0755 ${S}/cgi-bin/uptime.cgi ${D}/srv/www/cgi-bin
    39.      install -m 0755 ${S}/cgi-bin/test-cgi ${D}/srv/www/cgi-bin
    40.      install -m 0644 ${S}/cgi-bin/hello_world.php ${D}/srv/www/cgi-bin
    41.      install -m 0644 ${S}/cgi-bin/sqlite_test.php ${D}/srv/www/cgi-bin
    42.      install -m 0644 ${S}/cgi-bin/phpliteadmin.php ${D}/srv/www/cgi-bin
    43.      install -m 0644 ${S}/cgi-bin/phpliteadmin.config.php ${D}/srv/www/cgi-bin
    44. }

    Modify the peekpokecgi BitBake recipe to add root execution permissions.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl project-spec/meta-user/recipes-apps/peekpokecgi/peekpokecgi.bb

    peekpokecgi.bb

    1. #
    2. # This is the peekpokecgi aplication recipe
    3. #
    4. #

    5. SUMMARY = "peekpokecgi application"
    6. SECTION = "PETALINUX/apps"
    7. LICENSE = "MIT"
    8. LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
    9. SRC_URI = "file://peek.c \
    10.            file://poke.c \
    11.            file://peekstring.c \
    12.            file://Makefile \
    13.           "
    14. FILES_${PN} += "/srv/www/cgi-bin"
    15. S = "${WORKDIR}"
    16. CFLAGS_prepend = "-I ${S}/include"
    17. do_compile() {
    18.         oe_runmake
    19. }
    20. do_install() {
    21.         install -d ${D}/srv/www/cgi-bin
    22.         install -m 0755 ${S}/peek ${D}/srv/www/cgi-bin
    23.         install -m 0755 ${S}/poke ${D}/srv/www/cgi-bin
    24.         install -m 0755 ${S}/peekstring ${D}/srv/www/cgi-bin
    25.         chmod a+s ${D}/srv/www/cgi-bin/peek
    26.         chmod a+s ${D}/srv/www/cgi-bin/poke
    27.         chmod a+s ${D}/srv/www/cgi-bin/peekstring
    28. }

    Create an Apache BitBake append to realise the changes made to httpd.conf.

    Note the last entry is an addition to allow Apache to read index.php pages from directories & subdirectories without specifying the page explicitly.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ subl components/yocto/layers/meta-openembedded/meta-webserver/recipes-httpd/apache2/apache2_%.bbappend

    apache2.bbappend

    1. do_install_append() {

    2. sed -i 's@^#LoadModule cgid_module /usr/libexec/apache2/modules/mod_cgid.so@LoadModule cgid_module /usr/libexec/apache2/modules/mod_cgid.so@' ${D}/${sysconfdir}/${BPN}/httpd.conf

    3. sed -i 's@^DocumentRoot "/usr/share/apache2/default-site/htdocs"@DocumentRoot "/srv/www"@' ${D}/${sysconfdir}/${BPN}/httpd.conf

    4. sed -i 's@^<Directory "/usr/share/apache2/default-site/htdocs">@<Directory "/srv/www">@' ${D}/${sysconfdir}/${BPN}/httpd.conf

    5. sed -i 's@^    ScriptAlias /cgi-bin/ "/usr/libexec/apache2/modules/cgi-bin/"@    ScriptAlias /cgi-bin/ "/srv/www/cgi-bin/"@' ${D}/${sysconfdir}/${BPN}/httpd.conf

    6. sed -i 's@^<Directory "/usr/libexec/apache2/modules/cgi-bin">@<Directory "/srv/www/cgi-bin">@' ${D}/${sysconfdir}/${BPN}/httpd.conf

    7. sed -i 's@^    DirectoryIndex index.html@    DirectoryIndex index.html index.php@' ${D}/${sysconfdir}/${BPN}/httpd.conf

    8. }

    20. Build & package PetaLinux

    Rebuild PetaLinux to include the updates and package it ready for deployment.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ petalinux-build
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ petalinux-package --prebuilt --force

    21. Deploy firmware & software on Zedboard

    Deploy PetaLinux to the Zedboard via JTAG.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ petalinux-boot --jtag --prebuilt 3

    22. Check everything is working as expected

    To check everything is working as expected is simply a case of opening the various webpages and ensuring they are doing what is expected.

    Access the webserver by pointing at http://192.168.2.87 and open all the links.
    #### Part 6 - Revision Control ####

    23. Commit new & updated files

    Check GIT status to make sure all is well and there are no spurious elements.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ cd ../..
    steve@Desktop:~/projects/zedboard_linux$ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.

    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git restore <file>..." to discard changes in working directory)
            modified:   .petalinux/metadata
            modified:   project-spec/configs/config
            modified:   project-spec/configs/rootfs_config
            modified:   project-spec/meta-user/conf/petalinuxbsp.conf
            modified:   project-spec/meta-user/recipes-apps/peekpokecgi/peekpokecgi.bb
            modified:   project-spec/meta-user/recipes-apps/website/files/index.html
            modified:   project-spec/meta-user/recipes-apps/website/files/project.txt
            modified:   project-spec/meta-user/recipes-apps/website/files/uptime.js
            modified:   project-spec/meta-user/recipes-apps/website/website.bb

    Untracked files:
      (use "git add <file>..." to include in what will be committed)
            project-spec/meta-user/recipes-apps/website/files/cgi-bin/hello_world.php
            project-spec/meta-user/recipes-apps/website/files/cgi-bin/index.php
            project-spec/meta-user/recipes-apps/website/files/cgi-bin/phpliteadmin.config.php
            project-spec/meta-user/recipes-apps/website/files/cgi-bin/phpliteadmin.php
            project-spec/meta-user/recipes-apps/website/files/cgi-bin/sqlite_test.php
            project-spec/meta-user/recipes-apps/website/files/cgi-bin/test-cgi

    no changes added to commit (use "git add" and/or "git commit -a")
    Looks good!

    Add and commit the new & updated files, create an annotated tag and push the commits & tag up to the remote repository.
    steve@Desktop:~/projects/zedboard_linux/os/petalinux$ cd ../..
    steve@Desktop:~/projects/zedboard_linux$ git rm os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin/index.cgi
    steve@Desktop:~/projects/zedboard_linux$ git add os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin/test-cgi
    steve@Desktop:~/projects/zedboard_linux$ git add os/petalinux/project-spec/meta-user/recipes-apps/website/files/cgi-bin/*.php
    steve@Desktop:~/projects/zedboard_linux$ git add -f os/petalinux/components/yocto/layers/meta-openembedded/meta-webserver/recipes-httpd/apache2/apache2_%.bbappend
    steve@Desktop:~/projects/zedboard_linux$ git commit -am "Removed busybox-httpd Webserver and replaced it with a LAMP style stack of Apache, SQLite, PHP & myLiteAdmin."
    steve@Desktop:~/projects/zedboard_linux$ git push
    steve@Desktop:~/projects/zedboard_linux$ git tag -a v12.0 -m "PetaLinux, Peek/Poke, LED Runner, LAMP (Apache, SQLite, PHP & myLiteAdmin), Peek/Poke CGI, PL Access, Style Sheet, Register Bank & ID Strings with XSA from zedboard_leds_switches v5.0"
    steve@Desktop:~/projects/zedboard_linux$ git push origin v12.0

    24. Final checks

    Rebuild PetaLinux to include the updated GIT status, package it and deploy on the Zedboard.

    Access the webserver running on the Zedboard using a browser pointing at the Zedboard's IP address (192.168.2.87/cgi-bin/index.php). Click the Read ID buttons in both the Operating System Information & Firmware Information sectons to read the Identification information from the OS filesystem & PL address space. All being well the following should be displayed in the Operating System Information & Firmware Information sections.

    There should be no unsavoury comments after the version numbers!