tag:blogger.com,1999:blog-3451187217240039542024-03-19T10:13:07.013+01:00My Notepad.Helps me remember stuff.Unknownnoreply@blogger.comBlogger76125tag:blogger.com,1999:blog-345118721724003954.post-62623949885161066332015-06-24T08:21:00.003+02:002015-06-24T08:21:20.299+02:00Linux VNC and Mac OS X Screen Sharing I've found that in order to get <tt>x11vnc</tt> to work with the Mac OS X built-in VNC client ("Screen Sharing Application"), there options are required when starting the VNC server:<br />
<br />
<pre>$ x11vnc -display :0 -rfbauth /home/pi/.vnc/passwd -shared -rfbversion 3.3 -forever -bg
</pre><br />
The <tt>-shared</tt> option is key here. Judging by the log on the VNC server, I think Mac OS X will attempt multiple connections.<br />
<br />
For what it's worth, here's also how to auto-start the VNC server when the user logs into the LXDE desktop. Copy and paste this to <tt>~/.config/autostart/x11vnc.desktop</tt>:<br />
<br />
<pre>[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=VNC
Comment=
Exec=x11vnc -display :0 -rfbauth /home/pi/.vnc/passwd -shared -rfbversion 3.3 -forever -bg
StartupNotify=false
Terminal=false
Hidden=false
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-14212088832146735322015-06-21T19:28:00.000+02:002015-06-21T19:28:11.635+02:00Working around KiCAD Printing IssuesI'm having issues printing from KiCAD, specifically Pcbnew, on Ubuntu 15.04. I've seen similar things on earlier versions, and also found <a href="https://bugs.launchpad.net/kicad/+bug/1089027">this</a> bug report. Even though the bug report is closed and I'm using the right wx version, the problem persists for me. So I've searched for a workaround.<br />
<br />
Luckily, "plotting" from KiCAD works which makes it generate a PostScript file for each layer.<br />
<br />
However, I need the "Edge Cuts" layer and the bottom copper layer printed on a single page. The reason is that I'm printing my layouts on transparent film, and I'm using alignment marks on the edge cuts layer to help me tape two prints on top of each other. This increases the opaqueness of my print to a point where it's usable for me.<br />
<br />
So here's the steps it takes to get my PCB layout to a decent print:<br />
<ol><li>"Plot" the required layers from Pcbnew, leaving a bunch of PostScript files on disk.</li>
<li>Convert the PostScript files to PDF:<br />
<pre>$ for ps in *.ps ; do ps2pdf $ps ; done
</pre></li>
<li> Use <tt>pdftk</tt> to generate a single PDF from the relevant layers like this:<br />
<pre>$ pdftk <i>layout</i>-B_Cu.pdf background <i>layout</i>-Edge_Cuts.pdf output <i>layout</i>.pdf
</pre></li>
</ol><br />
<i>Update:</i> There's an option to include the "Edge Cuts" layer when plotting. Simply uncheck the "Exclude PCB edge layer from other layers" option as highlighted in the screenshot below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlzoxdtxa9RC_ZrHKs7X8MD2Q3E6uftHFITbAzL7W-s1GgZcxJkVp2mFRSjNb9gE96ZTJhkVbiNR34TCiYY9ySYXCkrFAEaqMcqUvng0ojZB6-ziyiGHg1Q_N1_mPeEX-mBTK5z0Q6g-AT/s1600/PCBnew_Screenshot_Plot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlzoxdtxa9RC_ZrHKs7X8MD2Q3E6uftHFITbAzL7W-s1GgZcxJkVp2mFRSjNb9gE96ZTJhkVbiNR34TCiYY9ySYXCkrFAEaqMcqUvng0ojZB6-ziyiGHg1Q_N1_mPeEX-mBTK5z0Q6g-AT/s320/PCBnew_Screenshot_Plot.png" /></a></div><br />
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-9469250117051544672014-09-10T18:02:00.001+02:002014-09-10T18:02:38.806+02:00Ubuntu 14.04, ThinkPad W520 and multiple Monitors<p>Here's a quick reminder of the commands that I use to switch between a single monitor setup (internal laptop screen) and two external, DVI-attached monitors on my ThinkPad W520 running Ubuntu 14.04 (x86_64).</p><br />
In order to switch to single-screen setup:<br />
<pre>phs@W520:~$ disper -s -d DP-2 -r auto
phs@W520:~$ disper -s -d LVDS-1 -r auto
</pre><br />
Switching to the two external monitors:<br />
<pre>phs@W520:~$ disper -s -d DP-2 -r auto
phs@W520:~$ disper -e -d DP-2,DP-3 -r auto
</pre><br />
All of this uses the stock, Ubuntu-provided driver. Didn't have much success with the nVidia drivers (from the repositories) on this laptop.<br />
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-33469557678632286212013-06-26T10:06:00.000+02:002013-06-26T10:06:58.192+02:00Xilinx USB Cable on Ubuntu<p>Here's what I did to install the "Xilinx Platform Cable USB II" on Ubuntu.</p><br />
First, install the following two packages:<br />
<br />
<pre>$ sudo aptitude install fxload libusb-dev
</pre><br />
Then, download and compile the USB driver for the cable:<br />
<br />
<pre>$ git clone git://git.zerfleddert.de/usb-driver
$ cd usb-driver
$ make
$ make lib32
$ ./setup_pcusb /opt/Xilinx/14.5/ISE_DS/ISE
</pre><br />
If everything worked, you should see the status LED on the programmer light up after it's plugged in.<br />
<br />
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-36572317811295366772013-06-23T12:41:00.000+02:002013-06-23T12:41:07.044+02:00Programming Avnet Spartan 3A FPGA Eval Board with Linux<p>I own a small FPGA Board by Avnet with a Spartan 3A FPGA on it. The board is nice, but unfortunately, the flash chips on the board aren't on the JTAG chain. Instead, there is a small PSoC microcontroller that lets you programm the flashes via UART. There is a Windows tool to perform that programming which is shipped with the board. Here's what I did to program the SPI configuration flash on Linux.</p><br />
<p>Via the <a href="http://fpgalibre.sourceforge.net/ingles.html">FPGALibre</a> site, I found a <a href="http://fpgalibre.sourceforge.net/ingles.html#tp82">link</a> to a tool called <a href="http://prdownloads.sourceforge.net/fpgalibre/astriaekipro-1.2.1.tar.bz2?download">ASTriAEKiPro</a>, which allows me to write to the FPGA SPI Configuration flash via UART and the PSoC microcontroller.</p><br />
Compiling the tool is as simple as running this command:<br />
<br />
<pre>$ make
</pre><br />
To erase the SPI configuration flash, I used this command:<br />
<br />
<pre>$ ./astriaekipro -p /dev/ttyACM0 -e
Avnet Spartan 3A Eval Kit Programmer v1.2.1
Copyright (c) 2009 Salvador E. Tropea <salvador at inti gob ar>
Copyright (c) 2009 Instituto Nacional de Tecnolog�a Industrial
Embedded BPI server provided by Avnet Inc. http://www.em.avnet.com/
Erasing the memory, be patient (>1 minute) ...
</pre><br />
To write a configuration to the SPI flash:<br />
<br />
<pre>$ ./astriaekipro -p /dev/ttyACM0 -w \
-b ~/sandbox/avnet_lpc/projects/13.3/avnet_lpc/avnet_i2c.bit
Avnet Spartan 3A Eval Kit Programmer v1.2.1
Copyright (c) 2009 Salvador E. Tropea <salvador at inti gob ar>
Copyright (c) 2009 Instituto Nacional de Tecnolog�a Industrial
Embedded BPI server provided by Avnet Inc. http://www.em.avnet.com/
Writing 235820 bytes to the serial flash, offset 0x0000000
Erasing: sector 3 (100.00 %)
Bytes written: 235820 (100.00 %)
All written!
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-47085297310459570052013-06-23T12:27:00.000+02:002013-06-23T12:27:43.887+02:00Edit Samsung TV Channel List on Linux<p>Samsung TVs suck when it comes to sorting the channel list. The work-around is to transfer the channel list to a PC and edit/sort it there. To edit the channel list on Linux, I found a tool called "<a href="http://wiki.samygo.tv/index.php5/SamyGO_ChanEdit_-_Chanel_Editor">SamyGO ChanEdit</a>" quite useful. Downloadable via <a href="http://sourceforge.net/projects/samygochanedit/files/">this link</a>.<br />
</p><br />
<p>The tool requires SWT which is installed in <tt>/usr/lib/java</tt> on my system. To start the tool, used the following command:</p><br />
<pre>java -classpath .:/usr/lib/java/swt-gtk-3.8.2.jar:SamyGO-ChanEdit-v54cd.jar gui.Main</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-16034720880142204742013-01-02T17:20:00.002+01:002013-01-24T21:26:53.157+01:00Bootable FreeBSD image on CompactFlash CardOne of the hacking toys I have is an Alix 1.C board which runs FreeBSD (9.1 at the time of writing). I started out net-booting the board but I thought it would be nice to boot the Alix board from a CompactFlash (CF) card I had laying around, too. In fact, I wanted to create a bootable image for the CF card which I could transfer to the CF card via <tt>dd(1)</tt>.<br />
<br />
<br />
<h2>Pre-requisites</h2>Before the show could start, I needed to find out the size of the CF card I had. I did this by writing all 0s to the card.<br />
<br />
<pre>root@T61p:~# dd if=/dev/zero of=/dev/sdb bs=512
dd: writing `/dev/sdb': No space left on device
1000945+0 records in
1000944+0 records out
512483328 bytes (512 MB) copied, 1099.51 s, 466 kB/s
</pre><br />
I did this by inserting the card in a laptop through an PCCard adapter. The laptop on which I do my hacking runs Linux (Ubuntu 12.10 at the time of writing), so the above is the output of a Linux command. So what this revealed is that the card has 1,000,944 blocks of 512 Bytes which is a total capacity of 512,483,328 Bytes or 488.74 MBytes.<br />
<br />
<h2>Setting up the Partition Table</h2>Now that we know the size of the CF card, we can create the bootable image. The first step is to create a file of exactly the size as the CF card. This can be done simply by running a command like this:<br />
<br />
<pre>[phs@freebsd ~]$ dd if=/dev/zero of=freebsd-alix.img bs=512 count=1000944
1000944+0 records in
1000944+0 records out
512483328 bytes transferred in 18.620906 secs (27521933 bytes/sec)
</pre><br />
Next, we need a virtual disk based on that image to work with. The solution is to create memory disk as described in the <a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/disks-virtual.html">FreeBSD handbook's section 19.13 on virtual disks</a>. As root, do this:<br />
<br />
<pre>freebsd# mdconfig -a -t vnode -f /home/phs/freebsd-alix.img -u 0
</pre><br />
This creates <tt>/dev/md0</tt>. Of course, nothing's on that disk, yet. The first thing to do is creating a partition table.<br />
<br />
<pre>freebsd# gpart create -s gpt md0
md0 created
</pre><br />
This creates an empty UEFI-compatible GPT partition table, but no partitions, yet. You can examine the partition table like this:<br />
<br />
<pre>freebsd# gpart show
(...)
=> 34 1000877 md0 GPT (488M)
34 1000877 - free - (488M)
</pre><br />
In order to boot FreeBSD from the image later, at least two partitions are required: A partition of 512K containing the boot code, and one partition containing the actual operating system. Because I wrote an <a href="http://www.phisch.org/website/glxiic">I2C device driver for the Alix 1.C</a>, I also want a swap partition so I have some space for kernel dumps.<br />
<br />
<pre>freebsd# gpart add -t freebsd-boot -l boot -s 512K md0
md0p1 added
freebsd# gpart add -t freebsd-swap -l swap -s 64M md0
md0p2 added
</pre><br />
Before adding the third partition for the FreeBSD operating system, find out how much space is left on the device by examining the partition table:<br />
<br />
<pre>freebsd# gpart show md0
=> 34 1000877 md0 GPT (488M)
34 1024 1 freebsd-boot (512k)
1058 131072 2 freebsd-swap (64M)
132130 868781 - free - (424M)
</pre><br />
Ok, now create the data partition:<br />
<br />
<pre>freebsd# gpart add -t freebsd-ufs -l rootfs -s 868781 md0
md0p3 added
</pre><br />
<h2>Embedding the boot code</h2>Now that the partition structure is laid out, it's time to make the image bootable. FreeBSD's <tt>gpart(8)</tt> manual page offers great information on what those files are and do: <tt>pmbr</tt> is a "protective MBF" which allows legacy, BIOS-based systems to boot the image. The MBR code searches the GPT for a <tt>freebsd-boot</tt> partition and starts the secondary boot code from there. In this case, that's <tt>gptboot</tt> which searches the GPT for a <tt>freebsd-ufs</tt> partition from which it loads <tt>/boot/loader</tt>.<br />
<br />
<br />
The following command writes the boot code to the image. Note that I'm using the files from <tt>/usr/obj</tt>, i.e. the ones most recently build from source and not the one's currently installed.<br />
<br />
<pre>freebsd# gpart bootcode -b /usr/obj/usr/src/sys/boot/i386/pmbr/pmbr
-p /usr/obj/usr/src/sys/boot/i386/gptboot/gptboot -i 1 md0
bootcode written to md0
</pre><br />
<h2>Initializing the root file system partition</h2>The third partition which is supposed to store the operating system must be initialized with a file system before it can be written.<br />
<br />
<pre>freebsd# newfs -L FreeBSD -U /dev/gpt/rootfs
/dev/gpt/rootfs: 424.2MB (868776 sectors) block size 32768, fragment size 4096
using 4 cylinder groups of 106.06MB, 3394 blks, 13696 inodes.
with soft updates
super-block backups (for fsck_ffs -b #) at:
192, 217408, 434624, 651840
</pre><br />
This creates an empty UFS2-based file system with soft-updates enabled on the partition which can be mounted:<br />
<br />
<pre>freebsd# mount /dev/md0p3 /mnt
freebsd# df -h
Filesystem Size Used Avail Capacity Mounted on
(...)
/dev/md0p3 410M 8.0k 377M 0% /mnt
</pre><br />
<h2>Installing FreeBSD to the bootable image</h2>Installing the operating system is as easy as this:<br />
<br />
<pre>[phs@freebsd /usr/src]$ sudo make installkernel KERNCONF=ALIX1C DESTDIR=/mnt
--------------------------------------------------------------
>>> Installing kernel ALIX1C
--------------------------------------------------------------
(...)
[phs@freebsd /usr/src]$ sudo make installworld DESTDIR=/mnt
(...)
[phs@freebsd /usr/src]$ sudo make DESTDIR=/mnt distrib-dirs distribution
(...)
</pre><br />
Before the image is really useful, you probably want to adjust a few config files here and there. Especially <tt>etc/fstab</tt> should be configured so that the root file system is found and mounted when booting:<br />
<br />
<pre>[phs@freebsd /mnt]$ cat etc/fstab
# Device Mountpoint FSType Options Dump Pass
/dev/ada0p3 / ufs ro 0 0
/dev/ada0p2 none swap sw 0 0
</pre><br />
In my case, the Alix 1.C board has a serial console but no screen. In order to get a login prompt on the serial console, <tt>etc/ttys</tt> needs to contain a line like this one:<br />
<br />
<pre>ttyu0 "/usr/libexec/getty std.115200" vt100 on secure
</pre><br />
Finally, a root password must be set:<br />
<br />
<pre># pw -V /mnt/etc usermod root -h 0
</pre><br />
When done, transfer the image to the CF card using <tt>dd(1)</tt>.<br />
<br />
<br />
<small><i>Update Jan 24th, 2013:</i> There are a few more files than just <tt>/etc/fstab</tt> that should be adjusted - added a few words about those.</small>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-345118721724003954.post-24941167546850362452012-09-16T16:56:00.001+02:002012-09-16T17:00:35.306+02:00Booting a PowerBook from a LiveCD image on an USB-Stick<p>I have an old Apple PowerBook G4 with a broken CD/DVD drive. For most practical purposes, the broken drive is no issue. However, if you're going to re-install the laptop, it becomes one. Luckily, the PowerBook is able to boot from USB...</p><br />
<p>At first, I tried following the instructions on "<a href="http://en.gentoo-wiki.com/wiki/LiveUSB_on_PPC">LiveUSB on PPC</a>" found in Gentoo's Wiki, but that didn't work out at first. I then found a blog entry titled "<a href="http://renevanbelzen.wordpress.com/2009/10/14/creating-a-bootable-usb-stick-with-mac-os-x-in-10-easy-steps/">Creating a bootable USB Stick with Mac OS X in 10 easy steps</a>". Combining the two lead to success, so here's what I did:</p><br />
<p><ul><li><p>I downloaded the latest PowerPC release of <a href="http://www.finnix.org">Finnix</a>, a " self-contained, bootable Linux CD distribution" from the project's front page.</p></li>
<li><p>I re-named the ISO image from <tt>finnix-ppc-105.iso</tt> to <tt>finnix-ppc-105.dmg</tt>. Also, I displayed the file's information in Finder by right-clicking on the file icon and selecting "Show Information". I doubt that this step is required but it certainly didn't do any harm.</p></li>
<li><p>From a shell, aka "Terminal Window", I used the command <tt>diskutil list</tt> to find the device path to my USB drive. In my case, it was <tt>/dev/disk6</tt>.</p></li>
<li>I then unmounted the drive by running<br />
<p><pre>$ diskutil unmountDisk /dev/disk6</pre></p></li>
<li>Using good, old dd(1), I wrote the disk image to the USB drive:<br />
<p><pre>$ sudo dd if=finnix-ppc-105.dmg of=/dev/disk6 bs=1m</pre><p></li>
<li>Finnally, I unmounted the drive by running:<br />
<p><pre>$ diskutil eject /dev/disk6</pre></p></li>
</ul></p><br />
<p>In order to boot the PowerBook from the USB drive, I had to drop into Open Firmware. In case you didn't know it, this is done by holding down <tt>Cmd</tt>+<tt>Option</tt>+<tt>o</tt>+<tt>f</tt> right after the computer is turned on.</p><br />
<p>The next step was to find the device node of the bootable USB drive. To do this, I browsed the device tree for any USB node that had a <tt>disk</tt> child node.<br />
<p><pre>> dev /
> ls
</pre></p>In my case, the USB drive was at <tt>/pci@f2000000/usb@1b,1/disk@1</tt>.</p><br />
<p>The instruction found on the Gentoo wiki assign the <tt>cd</tt> alias to that node, so I did that, too, by running:<br />
<p><pre>> devalias cd /pci@f2000000/usb@1b,1/disk@1
</pre></p><br />
<p>This allowed me to finally boot from the USB drive like this:<br />
<p><pre>> boot cd:,\\:tbxi
</pre></p></p>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-345118721724003954.post-34946849975784651782012-07-03T12:21:00.000+02:002012-07-04T10:52:49.600+02:00Ubuntu 11.10 on Lenovo W520<p>At work, I got a new laptop -- a Lenovo W520. It came with Ubuntu 11.10 ("Oneiric Ocelot") pre-installed by the support team. My first impression was that it worked pretty well, but I quickly discovered that I couldn't change the brightness of the display through the Fn+Home/End keys.</p><br />
<p>The W520 uses this "Optimus" technology with an integrated on-board graphics card plus a separate NVIDIA card, where both cards can be switched on-the-fly -- on Windows. The default installation used the high performance card and I suspected that the video card driver was keeping me from adjusting the brightness. As it turns out, after switching to the on-board Intel card, things worked fine. Here's what I needed to do:</p><br />
<p>First, I needed to disable the NVIDIA card in "the BIOS" and switch to the on-board card. There's an option somewhere under "Setup", then "Display", if I recall correctly.</p><br />
<p>Next, I changed the video card section in my <tt>/etc/X11/xorg.conf</tt> to read this:</p><br />
<pre>Section "Device"
Identifier "Device0"
Driver "intel"
Option "Shadow" "True"
Option "DRI" "True"
EndSection
</pre><br />
<p>In fact, I added the two <tt>Option</tt> lines later on and only changed the <tt>Driver</tt> line at first. I then discovered that most of the little try icons in the upper right corner of the Gnome desktop wouldn't show anymore. A look at <tt>/var/log/Xorg.0.log</tt> turned up some errors and running <tt>glxinfo</tt> yielded lines like these:</p><br />
<pre>Xlib: extension "GLX" missing on display ":0.0".</pre><br />
<p>Luckily, someone else ran into the same issues over at <a href="http://theiszm.wordpress.com/2010/06/27/glx-missing-on-display/">http://theiszm.wordpress.com/2010/06/27/glx-missing-on-display/</a>. As indicated there, I also ran these commands:</p><br />
<pre>$ sudo apt-get purge nvidia*
$ sudo apt-get install --reinstall xserver-xorg-video-intel \
libgl1-mesa-glx libgl1-mesa-dri xserver-xorg-core
$ sudo dpkg-reconfigure xserver-xorg
$ sudo update-alternatives --remove gl_conf /usr/lib/nvidia-current/ld.so.conf
</pre><br />
<p>The first command hinted that some "ubuntu-desktop" package would also be removed. I don't know what that is, but I don't miss it, yet. Anyways, after a final reboot, the brightness adjustment now works and all my tray icons are back in place.</p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-34467108071675635282011-11-02T14:52:00.019+01:002011-11-02T15:56:59.438+01:00CMake and C++ "Compile Time" PolymorphismFor a recent project of mine, I wanted to use what some people call "Compile Time Polymorphism" in C++. Here's how I implemented it.
<br />
<br />
Polymorphism in the context of programming computers usually refers to the ability to tread objects of a different data type through the same interface. In C++, this is often implemented through class inheritance and the use of virtual functions. The text book example of this concept is two classes, <tt>Cat</tt> and <tt>Dog</tt>, that inherit from a common super class <tt>Animal</tt>. <tt>Animal</tt> has a method <tt>makeSound()</tt> that is implemented by each subclass accordingly. In real software projects, polymorphism is used to hide multiple implementations behind a uniform interface. Here's an example of how this concept is usually used in C++.
<pre>class Animal {
public:
void makeSound(void) = 0;
};
class Cat : public Animal {
public:
void makeSound(void);
};
class Dog : public Animal {
public:
void makeSound(void);
};
</pre>
The issue with this code is that it requires the use of virtual functions which means you need a <tt>vtable</tt> for the concrete subclasses. Usually, as a programmer, you don't need to worry about <tt>vtable</tt>s as the compiler takes care of that for you. But let's take a look at how this works anyways. A <tt>vtable</tt> is basically a table of function pointers. For each of the concrete <i>classes</i> shown above, the <tt>vtable</tt> contains a pointer to the respective <tt>makeSound</tt> method. Also, each <i>object</i> carries a pointer to the <tt>vtable</tt>. At runtime, when a virtual method of an object is called, the pointer to the <tt>vtable</tt> is resolved to the actual <tt>vtable</tt>. From there, the address of the method is loaded and the call to it is made indirectly. So the use of virtual methods not only increases the size of your code, but also the size of your objects. In addition to that, it forces the compiler to use indirect function calls through pointers which are usually slower than direct function calls. Again, the compiler takes care of all of that, so this is purely informational.
<br />
<br />
All of the above is okay and in fact required if you don't know the concrete type of an object until the software actually runs. Also, in most software projects, the drawbacks don't matter and aren't even noticeable. But there are situations where you may not want to pay the price of virtual methods, e.g. in a resource limited embedded system.
<br />
<br />
Also, there are situations where it is known at <i>compile time</i> what the concrete implementation of an interface will be. This is true for example when you have an abstraction of an interface that is specific to a certain operating system: When you compile the software, you already know what the target operating system will be, so you can simply use and link to the right implementation of the interface, instead of post-poning the decision to runtime.
<br />
<br />
So how would you use polymorphism in C++ without the use of virtual methods?
<br />
<br />
Here's how you could do it:
<pre>typedef enum OperatingSystemImpl {
Darwin,
FreeBSD,
Linux
} OperatingSystemImpl_t;
template<operatingsystemimpl_t> struct OperatingSystemChoice;
class DarwinImpl;
class FreeBSDImpl;
class LinuxImpl;
template<> struct OperatingSystemChoice<darwin> {
typedef DarwinImpl m_type;
};
template<> struct OperatingSystemChoice<freebsd> {
typedef FreeBSDImpl m_type;
};
template<> struct OperatingSystemChoice<linux> {
typedef LinuxImpl m_type;
};
struct OperatingSystemService {
typedef OperatingSystemChoice< ... >::m_type m_type;
};
</linux></freebsd></darwin></operatingsystemimpl_t></pre>
Of course, the ellipsis must be expanded, but more on that later. What's important is how software using this construct would use the code:
<pre>
OperatingSystemService::m_type OsServiceObj;
</pre>
The snipped above would create an object of the correct type, dependend on what the ellipsis expands to. The neat thing is that the template compiler ensures that the ellipsis is expanded to a valid "type" as defined in <tt>enum OperatingSystemImpl</tt>. Also, it is made sure that the actual, underlying class is declared, e.g. <tt>class DarwinImpl</tt>.
<br />
<br />
In other words: If you tried to <i>compile</i> the software with the ellipsis expanded to <tt>Windows</tt>, you'd get a compilation error. If you had implemented this using classic polymorphism, you'd probably have some code that dynamically created the right object depending on what input is given. That means, you have to test your compiled code, feeding it an invalid type. This mean you must <i>run</i> your software. I'm convinced that finding problems earlier is better, so finding an issue when code is compiled is better than finding issues when code is run.
<br />
<br />
So back to how the ellipsis is expanded. Here's how CMake, a build system, comes into play. CMake uses input files that describe how the software needs to be compiled. Those input files, as with other build systems, are able to define compiler flags. Also, CMake defines a variable that contains the operating system's name. I suspect it's the output of <tt>uname</tt>. So here's what I added to my top level <tt>CMakeList.txt</tt> file:
<pre>
add_definitions("-DOPERATING_SYSTEM=${CMAKE_SYSTEM_NAME}")
</pre>
This makes the <tt>OPERATING_SYSTEM</tt> macro known to the pre-processor. So the code with the ellipsis can be re-written like this:
<pre>
struct OperatingSystemService {
typedef OperatingSystemChoice<operating_system>::m_type m_type;
};
</operating_system></pre>
Et voilà, the right type is picked when the code is compiled.
<br />
<br />
Here are the nice things about this: There is no need for virtual methods, eliminating the need for <tt>vtable</tt>s. Also, invalid or unsupported operating system types will be found at compile time vs. at runtime while the code for all supported operating systems will still be always compiled (just not used).
<br />
<br />
One downside may seem that you no longer have an enforced interface like when using purely virtual classes, i.e. the compiler may not tell you that you forgot to implement a newly added method to one of your implementation classes. However, this is more of a minor issue: You will still get a compilation error in that case, but only if you're compiling for the target system where you forgot to implement the newly added method.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-28320062407560392042011-03-05T12:38:00.003+01:002011-03-05T12:43:01.202+01:00Article about Interrupt Routing on x68Here's a good article about how <a href="http://people.freebsd.org/~jhb/papers/bsdcan/2007/article.pdf">PCI Interrupts for x86 Machines under FreeBSD</a> are implemented. While the article is targeted at FreeBSD, it also looks into the various interrupt routing mechanisms on x86 which apply to all systems software such as firmware and operating systems.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-37463173759548752052010-12-31T15:18:00.003+01:002010-12-31T15:23:16.853+01:00TianoCore and coreboot, againIt has been over two years since the <a href="http://phisch.blogspot.com/2008/10/more-on-tianocore-for-coreboot.html">last time</a> I worked on TianoCore for coreboot. These days I had some free time to spend and I used it to continue the project. I updated my code to the latest versions of coreboot and TianoCore and got it to work again in QEMU.
<br /><br />
Here's a <a href="https://phs.phisch.org/website/efiboot/screenshot.txt">"screenshot"</a> and <a href="https://phs.phisch.org/website/efiboot/">a few words</a> on what it's all about.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-40708849467609877582010-10-19T21:29:00.017+02:002010-10-20T21:14:56.436+02:00ImageMagick, libjpeg, etc. on Mac OS XHere's how I got ImageMagick with JPEG support to compile and run on Mac OS X 10.6 (Intel).
<br /><br />
First, I got the ImageMagick Source Code via Subversion, per the instructions from <a href="http://www.imagemagick.org/script/subversion.php">http://www.imagemagick.org/script/subversion.php</a>. Short version:
<pre>
$ svn co \
https://www.imagemagick.org/subversion/ImageMagick/branches/ImageMagick-6.6.5 \
ImageMagick-6.6.5
</pre>
Then, I pulled <a href="http://www.ijg.org/files/jpegsrc.v8b.tar.gz">libjpeg</a> from the <a href="http://www.ijg.org/">Independent JPEG Group</a>. I had to extract the source code to a subdirectory of the ImageMagick directory called <tt>jpeg</tt>, i.e. <tt>/path/to/ImageMagick-6.6.5/jpeg</tt>.
<br /><br />
Before I could compile any of the source code, I had to set three environment variables per <a href="http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&t=13145">this thread</a> on the ImageMagick forums:
<pre>
$ export CFLAGS="-isysroot /Developer/SDKs/MacOSX10.6.sdk \
-arch ppc -arch i386"
$ export CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.6.sdk \
-arch ppc -arch i386"
$ export LDFLAGS="-Wl,-syslibroot,/Developer/SDKs/MacOSX10.6.sdk \
-arch ppc -arch i386"
</pre>
Then, I compiled <tt>libjpeg</tt> via the via the standard <tt>./configure</tt> and <tt>make</tt> dance. I used these commands:
<pre>
$ cd jpeg
$ ./configure --prefix=/opt --disable-shared \
--disable-dependency-tracking
$ make -j 16
</pre>
Now, I was able to configure ImageMagick:
<pre>
</pre>
Be aware that the LDFLAGS path is different than the include path! If everything went well, you can now go on to build the imagemagick suite:
<pre>
$ ./configure --prefix=/opt --without-x --without-perl --with-jpeg \
--disable-shared --disable-dependency-tracking \
--enable-delegate-build --enable-osx-universal-binary
$ make -j 16
</pre>
This gave me statically linked binaries of the ImageMagick tools I was able to run on my Mac. I also tried to build dynamically linked binaries but failed. Because I don't need the dynamically linked version, I gave up after a while.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-45830284075573560662010-09-24T10:26:00.007+02:002010-10-19T22:12:53.987+02:00Testing with Google's C++ Test Framework (gtest)The other day I was playing around with Google's C++ Testing Framework (a.k.a. <a href="http://code.google.com/p/googletest/">gtest</a>). I tried to build the Code with Visual Studio 2008 Express and got some strange linker errors. I was able to solve the errors thanks to <a href="http://stackoverflow.com/questions/531941/how-to-setup-google-c-testing-framework-gtest-on-visual-studio-2005">this</a> site. In essence, I had to change the "Runtime Library" Setting in the C/C++ Code Generation options to "Multi-Threaded" for a release build and to "Multi-Threaded Debug" for a debug build.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-58710737904856704692010-08-25T15:00:00.005+02:002010-08-27T09:48:25.687+02:00Linker SetsReminder: When placing something in a dedicated section using <tt>__attribute__((section("foobar")))</tt>, the GNU toolchain will automatically add a symbol <tt>__start_foobar</tt> at the beginning and a symbol <tt>__stop_foobar</tt> at the end of the section.
<br /><br />
However, you will need a reference to that symbol in order to prevent the linker from optimizing the symbol away. In other words, you need to declare something like <tt>extern void *__start_foobar;</tt> and use it.
<br /><br />
When using the Microsoft toolchain, the symbols need to be added explicitly. To do that, one can make use of the fact that when the Microsoft linker encounters several sections with a "$_" in their name, it will merge the contents into one final output section. The name of the output section will be the common prefix of the declared sections. The beauty is that the contents are in the order of the section names.
<br /><br />
Here's an example: Supposed you placed something into a section called "foobar$_something". You can then add a variable <tt>__start_foobar</tt> into a section "foobar$_a" and a variable <tt>__stop_foobar</tt> into a section "foobar$_z". The resulting binary will have one section "foobar" with the contents of variable <tt>__start_foobar</tt> placed at the beginning, followed the contents of everything in section "foobar$_something" and the contents of the variable <tt>__stop_foobar</tt> at the end.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-84004979098286150532010-03-22T15:18:00.004+01:002010-03-22T15:22:36.776+01:00Fix Windows Full Text searchI've recently noticed that using the Windows full text search may not always turn up the expected results. Apparently, Windows requires a program to install a search filter for a given file type. There is some plain text filter available by default, but it's only registered for some endings. Source code files, e.g. Groovy files, will not be included, even though they contain nothing but plain ASCII text. Anyways, there's a <a href="http://support.microsoft.com/kb/309173/EN-US/">fix</a> available, but it's nowhere near intuitive...Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-84222712197630369992009-11-26T18:32:00.006+01:002009-11-26T18:40:55.024+01:00Building qfsm on Ubuntu 8.04I just tried to build <a href="http://qfsm.sourceforge.net/">qfsm</a> on Ubuntu 8.04. The only dependencies listed by qfsm are CMake and Qt 4.3.x - both of which are available through the Ubuntu packet manager.
<br/><br/>
However, when I followed the instructions provided along with the qfsm source code, I encountered this error message:
<pre>
[ 41%] Building CXX object CMakeFiles/qfsm.dir/src/ExportAHDLDlgImpl.o
In file included from qfsm-0.51.0-Source/src/ExportAHDLDlgImpl.h:21,
from qfsm-0.51.0-Source/src/ExportAHDLDlgImpl.cpp:21:
qfsm-0.51.0-Source/src/ui_ExportAHDLDlg.h:27: error: expected constructor, \
destructor, or type conversion before ‘class’
make[2]: *** [CMakeFiles/qfsm.dir/src/ExportAHDLDlgImpl.o] Error 1
make[1]: *** [CMakeFiles/qfsm.dir/all] Error 2
make: *** [all] Error 2
</pre>
It turns out that the definition of the <tt>QT_BEGIN_NAMESPACE</tt> macro was nowhere to be found on my system. Luckily, removing the corresponding lines in the qfsm source code allowed me to build the code just fine. I used this one-liner to remove the offending lines:
<pre>
$ for file in `grep -R QT_BEGIN_NAMESPACE * | awk -F : '{ print $1; }'` ; \
do sed -i -e '/QT_.*NAMESPACE/d' $file ; done
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-51875655364809158792009-09-18T13:11:00.002+02:002009-09-18T13:12:53.812+02:00Graphics CardFor some reason I have to look up the model of the graphics adapter in my thinkpad everytime I do an update... so here it goes: My T61p has a Quadro FX 570M in it.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-33408229517856747792009-07-24T15:25:00.003+02:002009-07-30T12:59:44.574+02:00Follow-UpA quick follow-up to <a href="http://phisch.blogspot.com/2008/10/parallels-for-linux.html">"Parallels" for Linux</a>. I've managed to run the Windows XP Partition on my Laptop inside KVM-88 like this:
<pre>
#!/bin/sh
export SDL_VIDEO_X11_DGAMOUSE=0
sudo qemu-system-x86_64 -hda /dev/sda -net nic -net user -m 1024 -cdrom fixntldr.iso -boot d -usb -usbdevice tablet -monitor stdio
</pre>
To send Ctrl+Alt+Del, I needed to enter this at the QEMU shell:
<pre>
sendkey ctrl-alt-delete
</pre>
<br />
<i>Edit (Jul 30th, 2009):</i> Here is a link to the <a href="http://en.wikibooks.org/wiki/QEMU/Monitor">QEMU console commands</a>.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-39056783098111281122009-04-28T21:29:00.003+02:002009-04-28T21:33:08.283+02:00Flashrom, Alix 1.C and FreeBSDI'm quite surprised that <a href="http://www.coreboot.org/Flashrom">flashrom</a> works pretty much out of the box on FreeBSD running on my Alix 1.C board. All I needed to do was comment out the code in the <tt>enable_flash_cs5536()</tt> function part of the <tt>chipset_enable.c</tt> file. Then, this simple command let me read out the BIOS image:
<pre>
$ flashrom -f -r -c "SST49LF040" bios.bin
</pre>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-18132146555807618722009-04-21T00:38:00.003+02:002009-04-21T00:54:51.227+02:00Avnet Spartan-3A Eval BoardSo I got this <a href="http://www.em.avnet.com/spartan3a-evl">Xilinx Spartan-3A Board by Avnet</a> recently. I bought it because it features a fairly large parallel flash chip (32 MBit) and an even larger SPI flash (128 Mbit).
<br /><br />
The board also features three clocks. One 16MHz clock is driven by an on-board oscillator while the other two (12 MHz and 32 kHz) are derived from a small controller.
<br /><br />
For the last few evenings, I tried to get the parallel flash to work. Since a single cycle of the slow 32 kHz clock meets the timing requirements of the parallel flash chip, I thought I'd try to use that before enhancing the design to also work w/ the faster clock(s).
<br /><br />
Unfortunately, that didn't work. When using the slow clock, mapping a signal directly to an output (LED) worked just fine, but routing the signal through more than few flip-flops didn't work at all. Apparently, the FPGA didn't like the slow clock too much.
<br /><br />
Bottom line: Took me three days to figure out that the board doesn't work with the slow 32 kHz clock. Oh well, at least I learned something new...Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-11734484388467006032009-02-26T22:13:00.009+01:002009-02-26T22:52:51.947+01:00SSH TricksMy shell scripting skills suck. So it comes naturally that I learn a lot every time I need to write a script. The trick I'm about to describe is so neat that I want to share it.
<br /><br />
Assume for a second that you need to execute a series of commands on a remote machine, but you can't pass them to SSH at once. Or consider that you might need to transfer a file over to a remote host and then extract it there. Normally, you'd need to create several SSH connections for this. In the "transfer, then extract" scenario, you need one connection for <tt>scp(1)</tt> and another one to extract the file on the remote host. Unless you have your public key in the remote host's <tt>~/.ssh/authorized_keys</tt> file, you need to enter your password for the remote host twice. It's probably not a big deal for most, but it's annoying at times.
<br /><br />
It might be obvious for some, but I recently found out that <tt>ssh(1)</tt> offers a solution for the problem described above. It allows you to open one connection in "master" mode to which other SSH processes can connect through a socket. The options for the "master" connection are:
<pre>
$ ssh -M -S /path/to/socket user@rhost
</pre>
Alternatively, the <tt>ControlPath</tt> and <tt>ControlMaster</tt> options can be set in the appropriate SSH configuration files. Other SSH processes that want to connect to the "master" connection only need to use the <tt>-S</tt> option. The authentication of the "master" connection will be re-used for all other connections that go through the socket. I'm not sure if SSH even opens a separate TCP connection.
<br /><br />
Going further, this can be used in scripts to save the user a lot of password typing, especially if the execution flow switches between local and remote commands a lot. At the beginning of the script, simply create a &qout;master" connection like this:
<pre>
$ ssh -M -S /path/to/socket -f user@rhost \
"while true ; do sleep 3600 ; done"
</pre>
It should be noted that the path to the socket can be made unique by using a combination of the placeholders <tt>%l</tt>, <tt>%h</tt>, <tt>%p</tt>, <tt>%r</tt> for the local host, remote host, port and remote username, respectively. The <tt>-f</tt> parameter makes SSH go into the background just before command execution. However, it requires that a command is specified, hence an endless loop of <tt>sleep(1)</tt> calls is added to the command line. Other SSH connections can be opened like this, not requiring any further user input (for authentication):
<pre>
$ ssh -S /path/to/socket user@rhost
</pre>
This leaves the problem of how the "master" process can be terminated when the script has finished. Some versions of SSH offer the <tt>-O</tt> parameter which can be used to <tt>check</tt> if the "master" is still running and, more importantly, to tell the "master" to <tt>exit</tt>. Note that in addition to the socket, the remote user and host need to be specified.
<pre>
$ ssh -S /path/to/socket -O check user@rhost
$ ssh -S /path/to/socket -O exit user@rhost
</pre>
However, there are still two problems to be solved. First, when the "master" quits, the dummy sleep loop continues to run. And second, how can the "master" be terminated if the given SSH version doesn't offer the <tt>-O</tt> parameter (short of killing the process by its PID)?Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-79172585979442912572009-02-04T11:35:00.002+01:002009-02-04T11:38:03.279+01:00brctl(8) and tunctl<tt>brctl</tt> is part of the <i>bridge-utils</i> package. Source code is available on <a href="http://sourceforge.net/project/showfiles.php?group_id=26089">Sourceforge</a>.
<br /><br />
<tt>tunctl</tt> is part of the User Mode Linux (UML) utilities available at the <a href="http://user-mode-linux.sourceforge.net/downloads.html">UML web site</a>.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-345118721724003954.post-76195026240604992772009-01-30T11:11:00.003+01:002009-01-30T11:25:02.608+01:00hexdump(1) lies!This week I found out that <tt>hexdump(1)</tt> on Linux doesn't seem to work with bytes but with half-words. I found out because I compared a byte-by-byte binary dump (output of a separate program) to the output of <tt>hexdump(1)</tt> (dumping the same data) and noticed that <tt>hexdump(1)</tt>'s output always swapped two adjacent bytes.
<br /><br />
Maybe I haven't found the right parameters, though.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-345118721724003954.post-68203301789516818782008-12-16T20:41:00.024+01:002008-12-17T23:26:04.963+01:00An Encrypted File-backed File System on FreeBSDThe following is a compilation of information, largely based on the FreeBSD Handbook, <a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/disks-virtual.html">Section 18.13</a> and <a href="http://www.freebsd.org/doc/en/books/handbook/disks-encrypting.html">Section 18.16</a>. This post describes how a file-backed, encrypted file system can be built and used on FreeBSD.
<h2>Prerequisites</h2>
In order to follow the steps below, the following prerequisites must be met:
<ul>
<li><tt>md(4)</tt> in the Kernel</li>
<li><tt>gbde(4)</tt> in the Kernel, i.e. <tt>kldload geom_bde</tt></li>
<li>The <tt>/etc/gbde</tt> directory must exist</li>
</ul>
<h2>First time installation</h2>
After those requirements are fullfilled, it's time to take the first step which is creating a file that will serve as the basis for the file system. There is no support for growing images so you need to allocate all space now. This command creates a 128 MByte file filled with zeros:
<pre>
$ dd if=/dev/zero of=encrypted.img bs=4k count=32768
</pre>
Next, create a memory disk which is based on the the image file created above. As root, do:
<pre>
# mdconfig -a -t vnode -f encrypted.img -u <unit>
</pre>
In the example above, the parametr <tt>-u <unit></tt> is optional and specifies a number which determines the number of the <tt>md(4)</tt> device. For example, if you use 4, then <tt>md4</tt> will be created.
<br /><br />
Now create a partition table which, e.g. one with an automatic layout:
<pre>
# bsdlabel -w md<unit> auto
</pre>
At this point, you have the equivalent of a hard disk w/ one or more FreeBSD partitions on it. Note that there is no filesystem, yet. In order to create an encrypted file system, an initialization step must be performed:
<pre>
# gbde init /dev/md0c -i -L /etc/gbde/encrypted.lock
</pre>
The initialization step opens an editor where the user is asked to enter a few parameters. Most notably it is probably sensible to change the <tt>sector_size</tt> to 4096, i.e. the page size on i386. When the editor is closed, the <tt>gbde(8)</tt> program asks for a password. This password will be used to encrypt the disk, so do not lose it. Note that the <tt>/dev/md0c</tt> parameter corresponds to the <tt>md(4)</tt> device which was previously created. The file of the lock name can be arbitrarily named as long as its ending is <tt>.lock</tt>. Also note that the lock file must be backed up as the file system cannot be easily accessed without the file.
<br /><br />
Now the encrypted device can be attached by running
<pre>
# gbde attach /dev/md0c -l /etc/gbde/encrypted.lock
</pre>
You'll be prompted for the password set in the previous step. If the password is accepted, you'll end up with a new disk device at <tt>/dev/md0c.bde</tt> on which you can operate the same way as on a regular disk. That means you'll need to create a file system, first.
<pre>
# newfs -U -O2 /dev/md0c.bde
</pre>
Make sure you use the <tt>.bde</tt> device node and not the raw memory disk as you'd end up without encryption. When you're done, it's time to mount the file system:
<pre>
# mkdir /encrypted
# mount /dev/md0c.bde /encrypted
</pre>
<h2>Unmounting the encrypted file system</h2>
Unmounting the file system is easy, but the <tt>gbde(4)</tt> device needs to be detached before the <tt>md(4)</tt> device can be destroyed.
<pre>
# umount /encrypted
# gbde detach /dev/md0c
# mdconfig -d -u 0
</pre>
<h2>Re-mounting an encrypted file system</h2>
Re-mounting is simple, but note that the FreeBSD handbook suggests that the file system be checked for errors before mounting:
<pre>
# mdconfig -a -t vnode -f encrypted.img
md0
# gbde attach /dev/md0c -l /etc/gbde/encrypted.lock
# fsck -p -t ffs /dev/md0c.bde
# mount /dev/md0c.bde encrypted
</pre>Unknownnoreply@blogger.com0