<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>G33K @ Work &#187; Development</title>
	<atom:link href="http://www.geekatwork.de/tag/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.geekatwork.de</link>
	<description>Basteleien eines Geeks</description>
	<lastBuildDate>Mon, 12 Jul 2010 08:38:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>OS Development Demo Code</title>
		<link>http://www.geekatwork.de/2010/07/12/os-development-demo-code/</link>
		<comments>http://www.geekatwork.de/2010/07/12/os-development-demo-code/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 08:36:14 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[OSDev]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[interrupts]]></category>
		<category><![CDATA[low level]]></category>
		<category><![CDATA[pic]]></category>
		<category><![CDATA[pit]]></category>
		<category><![CDATA[sigint]]></category>
		<category><![CDATA[x86]]></category>

		<guid isPermaLink="false">https://www.geekatwork.de/?p=274</guid>
		<description><![CDATA[A while ago, I wrote some demo code to demonstrate vari [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago, I wrote some demo code to demonstrate various things you need to do to write your own operating system.<br />
In May 2010 I held a lecture and workshop about this code and the concepts at <a href="http://events.ccc.de/sigint/2010/wiki/Hauptseite" target="_blank">SigInt conference in Cologne</a>, Germany.</p>
<p>I just thought that this code may be interesting to other people who did not attend this conference.<span id="more-274"></span></p>
<p><a href="http://github.com/G33KatWork/SigInt10OSWorkshop" target="_blank">The demo code</a> includes mainly x86 specific stuff and it is truly demo code, so don&#8217;t just copy it into another project. Even if it works at first sight, it it is highly likely to break sooner or later <img src='http://www.geekatwork.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>The code contains samples for:</p>
<ul>
<li>A small &#8220;Hello World&#8221; bootsector in realmode</li>
<li>A sample how to enable the A20 gate. This works at least in QEMU</li>
<li>Loading a barebone-kernel written in C by GRUB</li>
<li>Switching to protected mode and writing to the textmode framebuffer</li>
<li>Handling interrupts in protected mode using the old PIC</li>
<li>Configuring and using the old PIT (Timer)</li>
<li>Switching to longmode (64 Bit)</li>
<li>A multitasking demo how to do context switching</li>
</ul>
<p>The first two samples are completely written in Assembly and are loaded directly by the BIOS from a floppy drive. All other samples are mainly written in C spiced with some Assembly and are loaded from a FAT formatted floppy disk by a GRUB bootloader.</p>
<p>For those of you who speak german, here are the slides of the conference:<br />
<a href="http://events.ccc.de/sigint/2010/wiki/Fahrplan/events/3889.de.html" target="_blank">Talk</a><br />
<a href="http://events.ccc.de/sigint/2010/wiki/Fahrplan/events/3890.de.html" target="_blank">Workshop </a></p>
<p>If you do anything with this demo code, I would appreciate to hear about your project or experiences. Also, If there are specific questions or problems about/with this code which are not easily resolvable by Googling and using your brain, feel free to ask in the comments. <img src='http://www.geekatwork.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
 <p>Feel free to Flattr this post at <a href="http://flattr.com/" title="Flattr" target="_blank">flattr.com</a>, if you like it.</p> <p><a href="http://flattr.com/" title="Flattr" target="_blank"><img src="http://www.geekatwork.de/wp-content/plugins/flattrss/button-compact-static-100x17.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekatwork.de/2010/07/12/os-development-demo-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building and running your own Android</title>
		<link>http://www.geekatwork.de/2010/04/01/building-and-running-your-own-android/</link>
		<comments>http://www.geekatwork.de/2010/04/01/building-and-running-your-own-android/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 20:00:43 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[custom]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[fastboot]]></category>
		<category><![CDATA[G2]]></category>
		<category><![CDATA[HTC]]></category>
		<category><![CDATA[Magic]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[SPL]]></category>

		<guid isPermaLink="false">http://www.geekatwork.de/?p=197</guid>
		<description><![CDATA[Almost a year ago I bought an HTC Magic (also known as  [...]]]></description>
			<content:encoded><![CDATA[<p>Almost a year ago I bought an HTC Magic (also known as the G2) phone as a replacement for my iPhone.<br />
I was quite happy with it since it had the newest Android 1.5 and there was also an update released by Google to get it to version 1.6.</p>
<p>Now, that there are much fancier phones out there, like the Nexus One and Motorola Milestone, there must be a reason for people to buy them. The consequence about that is that they are holding back any updates to Android 2.0 or 2.1 for older phones. At least that&#8217;s my impression.</p>
<p>I also ever wanted to build and run my own Android since it is open source. At least that&#8217;s what Google says.<br />
My first steps were quite disappointing since there was no device specific package for my G2 in the source tree. There was only one for the HTC Dream (G1).</p>
<p>Yesterday I wanted to give it another try and it was a success. I will post my steps here which are especially for the HTC Magic (or G2, HTC Sapphire, MyTouch 3G, Google IO &#8211; they are all the same) but it should be possible to do this with other phones as long as you have all the device specific blobs like the GSM Baseband layer or low level hardware drivers for your specific device.<br />
Also keep in mind that this won&#8217;t be a normal guide like &#8220;How can I root this phone?&#8221; I assume that you more or less know what you are doing. So don&#8217;t blame me when you brick your phone: Shit happens and I&#8217;m not going to fix it.<span id="more-197"></span></p>
<p>Also, be careful what phone you have. There are 2 versions of the HTC Magic. One is the PVT32A and the other is PVT32B.<br />
The A version has more RAM compared to B. The phone sold by HTC on their own is the A version. Almost all others are B versions. My phone is a B variant.<br />
Check <a href="http://wiki.xda-developers.com/index.php?pagename=HTC_Sapphire_Hacking#sec01" target="_blank">this site</a> for any further information.</p>
<h2>The SPL</h2>
<p>The SPL is the Secondary Program Loader. The Initial Program Loader, which runs before the SPL is responsible for the basic bootstrapping of the processor inside the phone. Most of the time it is located on some on-die ROM and loads the SPL from flash.</p>
<p>The SPL itself is responsible for all kinds of boot services like booting from flash or receiving and handling data from the USB port with the fastboot protocol, which can be used for several maintenance tasks.</p>
<p>Usually, if you buy an OEM phone, you will get a shipment bootloader. Development phones will have an engineering bootloader.<br />
The difference between those two is that with the shipment bootloader, you will not be able to write the flash directly from your computer over the fastboot protocol, which you definitely want if you compile/develop your own Android. So the first step is to install an engineering loader.<br />
You can get several SPLs <a href="http://forum.xda-developers.com/showthread.php?t=529019" target="_blank">here</a>. I installed the Crios  loader.<br />
Just put the zip file on your SD-Card, boot a <a href="http://www.cyanogenmod.com/downloads/recovery-image" target="_blank">modified recovery image</a> via fastboot and apply the zip file from your SD:</p>
<pre class="brush:plain">fastboot boot cm-recovery-1.4.img</pre>
<p>The fastboot utility is available <a href="http://developer.htc.com/adp.html#s2" target="_blank">here</a> or from your compiled Android in the out/host/&lt;platform&gt;/bin/ subdirectory.<br />
To get your phone into fastboot mode, turn it off and hold the &#8220;back&#8221;-key while turning it on.</p>
<p>After flashing the new SPL you will have the engineering bootloader with security turned off.</p>
<h2>Getting the Android sourcecode</h2>
<p>If you want to build your own Android you obviously need to get the sourcecode. I did all the work on a Gentoo Linux. I don&#8217;t know how to do it under Windows or Mac OS.</p>
<p>First I thought to take the CyanogenMod repositories but they won&#8217;t check out completely because there seems to be missing at least one repository on github.</p>
<p>To get the official Google tree, just follow <a href="http://source.android.com/download" target="_blank">this guide</a>.</p>
<p>Essentially you just install the required packages, get the repo client, do the repo init, repo sync and you should be done.</p>
<h2>Get the binary blobs</h2>
<p>For the Sapphire board package, you will need to get some binary blobs for the camera, WLAN, baseband and several other things.</p>
<p>You can download them on the <a title="http://developer.htc.com/google-io-device.html" href="http://" target="_blank">HTC page for the Google IO</a>. Just download the recovery image for Android 1.6 and put it into the root of your Android source tree.<br />
After that you need to change the directory to vendor/htc/sapphire-open and execute the unzip-files.sh which extracts the blobs from the downloaded zipfile and puts them into the appropriate places.</p>
<h2>Building it</h2>
<p>After you prepared your environment, get back to the root of the source tree and do a</p>
<pre class="brush:plain">source build/envsetup.sh
lunch</pre>
<p>to setup several environment variables and select the build target, which will be <em>aosp_sapphire_eu-userdebug</em> in our case.</p>
<p>After that you can just execute a</p>
<pre class="brush:plain">make -j3</pre>
<p>to start the build. You can adjust the number behind the -j parameter to your machine. If you have n cores, the number you normally use is n+1. This is not essential for a successful build, but if you have 2 or more cores, you should use them for the build.<br />
Now it&#8217;s time to ge some beautiful delicious black coffee or a cold bootle of <a href="http://www.club-mate.de" target="_blank">Club-Mate</a>, go for a walk or take a nap. This will take quite some time.</p>
<h2>Common errors during the build</h2>
<p>I ran into several erros while buildng. All of them were specific to my environment.</p>
<ul>
<li><em>no rule to make target `run-java-tool&#8217;</em> during build<br />
Solution: Just execute a <em>export PATH=$(java-config -O)/bin:$PATH</em> and the error you should be gone</li>
<li>Java 1.6 is installed.<br />
Solution: Do an <em>ACCEPT_LICENSE=&#8221;*&#8221; emerge =sun-jdk-1.5.0.22</em> and select the 1.5 JDK with eselect.</li>
<li>Building the emulator fails with something like <em>prebuilt/linux-x86/sdl/include/SDL/SDL_syswm.h:55:22: error: X11/Xlib.h: No such file or directory</em><br />
Solution: Do an <em>emerge libX11</em></li>
</ul>
<h2>Installing the built images on your phone</h2>
<p>After the build finished successful you will have everything in the <em>out</em> subdirectory.</p>
<p>Thanks to the engineering SPL, you can now install the built images using fastboot:</p>
<pre class="brush:plain">export ANDROID_PRODUCT_OUT="/path/to/android/root/out/target/product/sapphire-open"
fastboot flashall</pre>
<p>Be sure your phone is in fastboot mode.</p>
<p>After you flashed the images you should boot the recovery image, mentioned in the SPL section, again and wipe the userdata partition.<br />
This will cause a data loss. Anyway, you should have done a backup with nandroid in the modified recory image before messing around with your phone&#8217;s firmware <img src='http://www.geekatwork.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2>The result</h2>

<a href='http://www.geekatwork.de/2010/04/01/building-and-running-your-own-android/about/' title='about'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/about-150x150.png" class="attachment-thumbnail" alt="about" title="about" /></a>
<a href='http://www.geekatwork.de/2010/04/01/building-and-running-your-own-android/menu/' title='menu'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/menu-150x150.png" class="attachment-thumbnail" alt="menu" title="menu" /></a>
<a href='http://www.geekatwork.de/2010/04/01/building-and-running-your-own-android/main/' title='main'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/main-150x150.png" class="attachment-thumbnail" alt="main" title="main" /></a>

<h2>Next steps</h2>
<p>As you can see from the images above, all of the Google applications are missing. The next step would be to take them from an official Google image and put them on your phone. I think cyanogen already wrote a script for doing this for his builds. I haven&#8217;t checked this out yet.</p>
<p>Anyway, we have our very own Android 2.1 running.<br />
If you want to use it on a daily basis you should consider building a stable branch and using this instead of the master branch.</p>
<p>If you&#8217;ve got any questions or problems, just leave them in the comments and we will try to figure them out.</p>
<p><strong>Update:</strong> The cyanogenmod repositories do check out. I just used the wrong manifest repository.<br />
If you want to give it a try, just do a</p>
<pre class="brush:plain">repo init -u git://github.com/cyanogen/android.git -b eclair
repo sync</pre>
<p>instead of using the Google repository. <a href="http://wiki.cyanogenmod.com/index.php/Building_from_source" target="_blank">Have a look here</a> for more information.</p>
<p>General useful information, like adding your own target, creating keys for signing etc. can be found <a href="http://pdk.android.com/online-pdk/guide/build_new_device.html" target="_blank">here</a>.</p>
<script type="text/javascript">
var flattr_wp_ver = '0.9.11';
var flattr_uid = 'G33KatWork';
var flattr_url = 'http://www.geekatwork.de';
var flattr_lng = 'en_GB';
var flattr_cat = 'text';
var flattr_tag = 'blog,wordpress,rss,feed';
var flattr_btn = 'large';
var flattr_tle = 'G33K @ Work';
var flattr_dsc = 'Basteleien eines Geeks';
</script>
<script src="http://api.flattr.com/button/load.js?v=0.2" type="text/javascript"></script> <p>Feel free to Flattr this post at <a href="http://flattr.com/" title="Flattr" target="_blank">flattr.com</a>, if you like it.</p> <p><a href="http://flattr.com/" title="Flattr" target="_blank"><img src="http://www.geekatwork.de/wp-content/plugins/flattrss/button-compact-static-100x17.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekatwork.de/2010/04/01/building-and-running-your-own-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>StudiPlaner</title>
		<link>http://www.geekatwork.de/projekte/studiplaner/</link>
		<comments>http://www.geekatwork.de/projekte/studiplaner/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 19:06:03 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[datenbank]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[studiplaner]]></category>

		<guid isPermaLink="false">http://www.geekatwork.de/?page_id=149</guid>
		<description><![CDATA[Der StudiPlaner ist eine Datenbankbasierte Applikation, [...]]]></description>
			<content:encoded><![CDATA[<p>Der StudiPlaner ist eine Datenbankbasierte Applikation, die ich damals zu Beginn meines Studiums angefangen habe zu entwickeln.<br />
Grund war, dass ich einfach irgendeine Applikation unter .NET mit einer Datenbankschnittstelle schreiben wollte.</p>
<p>Es gibt einige Möglichkeiten Vorlesungen, Professoren, Dokumente, Termine etc. anzulegen, die Software ist aber lange nicht fertig und ich habe die Lust verloren weiter an ihr zu entwickeln.</p>
<p>Der Quellcode baut in der aktuellen Revision auch nicht, da ich mitten in einer Migration von SQL Compact Edition auf ein SQLite stecke. Einige Revisionen vorher sollten aber funktionieren.</p>
<p>Den Code findet man auf <a href="http://github.com/G33KatWork/StudiPlaner" target="_blank">GitHub</a>.</p>
<p>Screenshots:<br />

<a href='http://www.geekatwork.de/projekte/studiplaner/800px-studiplaner3/' title='800px-Studiplaner3'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/800px-Studiplaner3-150x150.png" class="attachment-thumbnail" alt="800px-Studiplaner3" title="800px-Studiplaner3" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/800px-studiplaner7/' title='800px-Studiplaner7'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/800px-Studiplaner7-150x150.png" class="attachment-thumbnail" alt="800px-Studiplaner7" title="800px-Studiplaner7" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/800px-studiplaner14/' title='800px-Studiplaner14'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/800px-Studiplaner14-150x150.png" class="attachment-thumbnail" alt="800px-Studiplaner14" title="800px-Studiplaner14" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/800px-studiplaner15/' title='800px-Studiplaner15'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/800px-Studiplaner15-150x150.png" class="attachment-thumbnail" alt="800px-Studiplaner15" title="800px-Studiplaner15" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/erinnerung/' title='erinnerung'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/erinnerung-150x150.png" class="attachment-thumbnail" alt="erinnerung" title="erinnerung" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/fachbearbeiten/' title='fachbearbeiten'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/fachbearbeiten-150x150.png" class="attachment-thumbnail" alt="fachbearbeiten" title="fachbearbeiten" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/fachvorlesungszeiten/' title='fachvorlesungszeiten'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/fachvorlesungszeiten-150x150.png" class="attachment-thumbnail" alt="fachvorlesungszeiten" title="fachvorlesungszeiten" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/faecher/' title='faecher'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/faecher-150x150.png" class="attachment-thumbnail" alt="faecher" title="faecher" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/links/' title='links'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/links-150x150.png" class="attachment-thumbnail" alt="links" title="links" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/studiplaner1/' title='Studiplaner1'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/Studiplaner1-150x150.png" class="attachment-thumbnail" alt="Studiplaner1" title="Studiplaner1" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/studiplaner6/' title='Studiplaner6'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/Studiplaner6-150x150.png" class="attachment-thumbnail" alt="Studiplaner6" title="Studiplaner6" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/termin_erstellen/' title='termin_erstellen'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/termin_erstellen-150x150.png" class="attachment-thumbnail" alt="termin_erstellen" title="termin_erstellen" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/termine_ansichten/' title='termine_ansichten'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/termine_ansichten-150x150.png" class="attachment-thumbnail" alt="termine_ansichten" title="termine_ansichten" /></a>
<a href='http://www.geekatwork.de/projekte/studiplaner/termine/' title='termine'><img width="150" height="150" src="http://www.geekatwork.de/wp-content/uploads/termine-150x150.png" class="attachment-thumbnail" alt="termine" title="termine" /></a>
</p>
 <p>Feel free to Flattr this post at <a href="http://flattr.com/" title="Flattr" target="_blank">flattr.com</a>, if you like it.</p> <p><a href="http://flattr.com/" title="Flattr" target="_blank"><img src="http://www.geekatwork.de/wp-content/plugins/flattrss/button-compact-static-100x17.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekatwork.de/projekte/studiplaner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I can haz FPGA?</title>
		<link>http://www.geekatwork.de/2010/01/17/i-can-haz-fpga/</link>
		<comments>http://www.geekatwork.de/2010/01/17/i-can-haz-fpga/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 21:23:30 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Elektronik]]></category>
		<category><![CDATA[FPGA]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Xilinx]]></category>

		<guid isPermaLink="false">http://www.geekatwork.de/?p=89</guid>
		<description><![CDATA[Da ises weg, das Weihnachtsgeld.

Draufgegangen ist d [...]]]></description>
			<content:encoded><![CDATA[<p>Da ises weg, das Weihnachtsgeld.</p>
<p>Draufgegangen ist das unter anderem für dieses hübsche, aber leider teure FPGA-Board mit einem Xilinx Spartan 3 FPGA:<br />
<a href="http://www.geekatwork.de/wp-content/uploads/2010-01-12-23.48.01-e1263764275949.jpg" rel="lightbox"><img class="alignnone size-medium wp-image-90" title="spartan3an" src="http://www.geekatwork.de/wp-content/uploads/2010-01-12-23.48.01-300x225.jpg" alt="" width="300" height="225" /></a></p>
<p><span id="more-89"></span>Wie man sieht, sieht man ein A auf dem LCD Display. Viel mehr habe ich damit noch nicht zustande gebracht. Besonders einfach wirds einem aber sowieso nicht gemacht. Das Ding ist halt kein Prozessor, mit dem man sequentielle Abläufe durch das Ausführen eines Programms abbilden kann, sondern pure Digitaltechnik.<br />
Durch VHDL wird einem das Beschreiben etwas einfacher gemacht, die Vorgänge laufen aber alle parallel in diesem Chip ab. Signale warten nicht einfach so auf ein Ereignis.</p>
<p>Signalabläufe wie sie von einem Displaycontroller erwartet werden können auch nur über eine Statemachine modelliert werden. Man hüpft also von einem Zustand in den anderen und legt die passenden Signale an die Leitungen. Danach springt man meistens wieder in eine Warteschleife, weil der LCD-Controller üblicherweise langsamer ist als so ein FPGA.</p>
<p>Da man das ganze äußerst schlecht debuggen kann, simuliert man im Vorfeld die Abläufe. Man schreibt also erstmal sein Modul in VHDL und darf sich dann auch noch darum kümmern einen Sogenannten Testbench zu schreiben. Dieser Testbench ist dann dafür zuständig die passenden Signale, die normalerweise durch externe Quellen erzeugt werden, an das Modul zu legen, um das alles in Software abbilden zu können.</p>
<p>Nachdem man dann die Simulation für einige Milisekunden ausgeführt hat, sieht das so aus:<br />
<a href="http://www.geekatwork.de/wp-content/uploads/rs232_wave.png" rel="lightbox"><img class="alignnone size-medium wp-image-91" title="RS232 Simulation" src="http://www.geekatwork.de/wp-content/uploads/rs232_wave-300x101.png" alt="" width="300" height="101" /></a></p>
<p>Auf diesem Bild sieht man die Simulation eines RS232 Moduls. Die Länge eines Bits ist hier 8,6µs, was eine Baudrate von 115200 pro Sekunde ergibt.<br />
Als erstes wird in tx_data das Byte abgelegt, welches üertragen werden soll. Dann zieht man tx_start kurz auf High, was man hier nicht sieht, da es bereits 40ns nach dem Start passiert, und die Übertragung startet. Erst kommt das Startbit auf der TXD-Leitung, dann eine 0, dann eine 1 usw. bis das Stopbit kommt und die Leitung wieder auf &#8220;Standby&#8221; geht und somit 0xAA übertragen wurde. RS232 überträgt das niederwertigste Bit zuerst.</p>
<p>Analog läuft das mit dem Empfangen ab.</p>
<p>In VHDL sieht das ganze dann so aus:</p>
<pre class="brush:plain">library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity RS232 is
    Generic ( Clockrate : integer   := 50000000;  -- Hertz
              Baudrate  : integer   :=  9600      -- Bits/Sec
             );
    Port ( RXD      : in   STD_LOGIC;
           RX_Data  : out  STD_LOGIC_VECTOR (7 downto 0);
           RX_Busy  : out  STD_LOGIC;
           TXD      : out  STD_LOGIC;
           TX_Data  : in   STD_LOGIC_VECTOR (7 downto 0);
           TX_Start : in   STD_LOGIC;
           TX_Busy  : out  STD_LOGIC;
           CLK      : in   STD_LOGIC
           );
end RS232;

architecture Behavioral of RS232 is
signal txstart : std_logic := '0';
signal txsr    : std_logic_vector  (9 downto 0) := "1111111111";
signal txbitcnt : integer range 0 to 10 := 10;
signal txcnt    : integer range 0 to (Clockrate/Baudrate)-1;

signal rxd_sr  : std_logic_vector (3 downto 0) := "1111";
signal rxsr    : std_logic_vector (7 downto 0) := "00000000";
signal rxbitcnt : integer range 0 to 9 := 9;
signal rxcnt   : integer range 0 to (Clockrate/Baudrate)-1; 

begin
   send: process(CLK)
   begin
      if rising_edge(CLK) then
         txstart &lt;= TX_Start;
         if (TX_Start = '1' and txstart = '0') then
            txcnt    &lt;= 0;
            txbitcnt &lt;= 0;
            txsr     &lt;= '1' &amp; TX_Data &amp; '0';
         else
            if(txcnt&lt;(Clockrate/Baudrate)-1) then
               txcnt &lt;= txcnt + 1;
            else
               if (txbitcnt &lt; 10) then
                  txcnt    &lt;= 0;
                  txbitcnt &lt;= txbitcnt + 1;
                  txsr     &lt;= '1' &amp; txsr(txsr'left downto 1);
               end if;
            end if;
         end if;
      end if;
   end process;
   TXD     &lt;= txsr(0);
   TX_Busy &lt;= '1' when (txbitcnt &lt; 10) else '0';

   receive: process(CLK)
   begin
      if rising_edge(CLK) then
         rxd_sr &lt;= rxd_sr(rxd_sr'left - 1 downto 0) &amp; RXD;
         if (rxbitcnt &lt; 9) then
            if(rxcnt &lt; (Clockrate / Baudrate) - 1) then
               rxcnt    &lt;= rxcnt + 1;
            else
               rxcnt    &lt;= 0;
               rxbitcnt &lt;= rxbitcnt + 1;
               rxsr     &lt;= rxd_sr(rxd_sr'left - 1) &amp; rxsr(rxsr'left downto 1);
            end if;
         else
            if (rxd_sr(3 downto 2) = "10") then
               rxcnt    &lt;= ((Clockrate / Baudrate) - 1) / 2;
               rxbitcnt &lt;= 0;
            end if;
         end if;
      end if;
   end process;
   RX_Data &lt;= rxsr;
   RX_Busy &lt;= '1' when (rxbitcnt &lt; 9) else '0';

end Behavioral;</pre>
<p>Mit einer &#8220;entity&#8221; beschreibt man, dass es irgendein Modul mit entsprechendem Namen gibt und welche Leitungen da rein und rausgehen.<br />
Im &#8220;Behaviour&#8221; beschreibt man dann, wie sich das Modul verhält und welche internen Signale oder Variablen es gibt. Wir haben in diesem Fall 2 Prozesse. Einen zum Senden und einen zum Emmpfangen. Jeder dieser Prozesse kann gleichzeitig ausgeführt werden.</p>
<p>Der passende Testbench zu diesem RS232 Modul sieht dann so aus:</p>
<pre class="brush:plain">LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;

ENTITY rs232_tb IS
END rs232_tb;

ARCHITECTURE behavior OF rs232_tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT RS232
   GENERIC ( Clockrate : integer := 50000000;
             Baudrate : integer := 115200);
    PORT(
         RXD : IN  std_logic;
         RX_Data : OUT  std_logic_vector(7 downto 0);
         RX_Busy : OUT  std_logic;
         TXD : OUT  std_logic;
         TX_Data : IN  std_logic_vector(7 downto 0);
         TX_Start : IN  std_logic;
         TX_Busy : OUT  std_logic;
         CLK : IN  std_logic
        );
    END COMPONENT;

   --Inputs
   signal RXD : std_logic := '0';
   signal TX_Data : std_logic_vector(7 downto 0) := (others =&gt; '0');
   signal TX_Start : std_logic := '0';
   signal CLK : std_logic := '0';

   --Outputs
   signal RX_Data : std_logic_vector(7 downto 0);
   signal RX_Busy : std_logic;
   signal TXD : std_logic;
   signal TX_Busy : std_logic;

  constant clk_period : time := 20 ns;

BEGIN

  -- Instantiate the Unit Under Test (UUT)
   uut: RS232 PORT MAP (
          RXD =&gt; RXD,
          RX_Data =&gt; RX_Data,
          RX_Busy =&gt; RX_Busy,
          TXD =&gt; TXD,
          TX_Data =&gt; TX_Data,
          TX_Start =&gt; TX_Start,
          TX_Busy =&gt; TX_Busy,
          CLK =&gt; CLK
        );

   clk_process :process
   begin
      CLK &lt;= '0';
      wait for clk_period/2;
      CLK &lt;= '1';
      wait for clk_period/2;
   end process;

   -- Stimulus process
   stim_proc: process
   begin
      RXD &lt;= '1';            --idle
      wait for clk_period*2;

      TX_Data &lt;= "10101010";
      TX_Start &lt;= '1';

      wait for clk_period*5;
      TX_Start &lt;= '0';

      wait for clk_period*5000;

      --startbit
      RXD &lt;= '0';
      --435 clock cycles by 20ns each = 8,7us = length of bit with 115200 baud
      wait for clk_period*435;

      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;
      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;
      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;
      RXD &lt;= '0';
      wait for clk_period*435;
      RXD &lt;= '1';
      wait for clk_period*435;

      --stopbit and idle
      RXD &lt;= '1';

      wait;
   end process;

end;</pre>
<p>Der Aufbau ist ähnlich wie vorhin. Die Entity hier enthält jedoch keine Ein- oder Ausgabesignale, da hier später nur die internen Signale dieses Testbenches im Simulator betrachtet werden. Natürlich kann man später in der Waveform noch weitere Signale hinzufügen. Zum Beispiel interne Signale aus dem getesteten Modul.<br />
Im Behaviour wird dann als erses die Komponente RS232 definiert. Es gibt also irgendwo ein solches Modul, das später hier genutzt werden kann. Darauf folgend kommen wieder einige Signale, denen man später in Prozessen Werte zuweisen kann oder von denen man Werte auf den Leitungen abgreifen kann.<br />
Danach wird ein RS232 Modul mit dem Namen uut (&#8220;unit under test&#8221;) instanziert und die Ports des Moduls werden mit den internen Signalen verknüpft.<br />
Dann folgen wieder Prozesse. Der erste generiert das Clocksignal und der zweite ist für den eigentlichen Ablauf des Test verantwortlich. Das Senden ist hier relativ einfach: Wert in tx_data schreiben, für kurze Zeit an tx_start ziehen und dann beginnt die Übertragung.</p>
<p>Der Empfangstest ist dahingehend schwieriger, dass jedes Bit für eine bestimmte Zeit anliegen muss, wie es in Wirklichkeit auf einem Kabel auch der Fall wäre.<br />
clk_period*435 entspricht hier exakt 8,7µs, was wiederrum ungefähr 115200 Baud/s entspricht: 20ns*435 = 8700ns = 8,7µs</p>
<p>Als nächstes werde ich mich mal an den VGA Ausgang setzen und probieren ein Bild zu zaubern. Danach ist allerdings auch schon der DDR2-Speichercontroller dran: Für ein 12 Bit VGA-Bild bei einer Auflösung von 640&#215;480 Pixeln sind schon 450KB Video RAM nötig. Mit double buffering sind wir dann bei 900KB.</p>
<p><strong>Update:</strong> Das RS232 Modul stammt im übrigen von <a href="http://www.lothar-miller.de/s9y/categories/42-RS232" target="_blank">hier</a>. Lediglich den Testbench habe ich mir dann noch dazugeschrieben.</p>
<script type="text/javascript">
var flattr_wp_ver = '0.9.11';
var flattr_uid = 'G33KatWork';
var flattr_url = 'http://www.geekatwork.de';
var flattr_lng = 'en_GB';
var flattr_cat = 'text';
var flattr_tag = 'blog,wordpress,rss,feed';
var flattr_btn = 'large';
var flattr_tle = 'G33K @ Work';
var flattr_dsc = 'Basteleien eines Geeks';
</script>
<script src="http://api.flattr.com/button/load.js?v=0.2" type="text/javascript"></script> <p>Feel free to Flattr this post at <a href="http://flattr.com/" title="Flattr" target="_blank">flattr.com</a>, if you like it.</p> <p><a href="http://flattr.com/" title="Flattr" target="_blank"><img src="http://www.geekatwork.de/wp-content/plugins/flattrss/button-compact-static-100x17.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekatwork.de/2010/01/17/i-can-haz-fpga/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Systemprogrammierung</title>
		<link>http://www.geekatwork.de/2010/01/03/systemprogrammierung/</link>
		<comments>http://www.geekatwork.de/2010/01/03/systemprogrammierung/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 00:08:14 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[OSDev]]></category>
		<category><![CDATA[The usual rants]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[Virtualisierung]]></category>

		<guid isPermaLink="false">http://www.geekatwork.de/?p=81</guid>
		<description><![CDATA[Mein momentanes Interessenfeld bezieht sich ja sehr sta [...]]]></description>
			<content:encoded><![CDATA[<p>Mein momentanes Interessenfeld bezieht sich ja sehr stark auf alles, was mit System- und Hardwarenaher Programmierung zu tun hat.<br />
Da ich auf der Zugfahrt zum <a href="http://events.ccc.de/congress/2009" target="_blank">26c3</a> nicht besonders viel zu tun hatte und die AMD und Intel Dokumentationen auf meinem Rechner hatte, habe ich mal angefangen mich um die <a href="http://de.wikipedia.org/wiki/Virtualisierung_%28Informatik%29" target="_blank">Virtualisierungsfunktionen</a>, die diese beiden Hersteller da so in ihre Prozessoren verpflanzen, zu kümmern.<span id="more-81"></span></p>
<p>Nachdem ich dann auch irgendwann mal raushatte, wie ich das vierstufige (!) Paging mit 4KB großen Pages beim Booten zusammenbauen konnte, um so einen Prozessor in den <a href="http://de.wikipedia.org/wiki/AMD64#Betriebsmodi" target="_blank">Long Mode</a> zu bekommen, hab ich mich mal an die Virtualisierung machen wollen.<br />
Zu diesem Zeitpunkt saß ich allerdings schon im Hackcenter.</p>
<p>Wie ich dann, mal wieder, feststellen musste, hat so ein Low Level Zeug einen unglaublichen Rattenschwanz, den man immer wieder hinter sich herzieht. In diesem konrekten Fall brauchte ich also ein vernünftiges <a href="http://de.wikipedia.org/wiki/Interrupt" target="_blank">Interrupthandling</a>. Ist ja schnell implementiert, dachte ich mir und kopier mir meinen Code aus meinen anderen <a href="http://www.geekatwork.de/projekte/geexos/" target="_self">Projekten</a> fröhlich zusammen.</p>
<p>Interrupts konnte ich dann handlen. Problem war jetzt nur, dass 2 Instruktionen nach dem Aktivieren der Interrupts sofort der Interrupt #8 auftrat, was nach Dokumentation ein Double Fault gewesen sein müsste. Dieser tritt aber nur nach einer fatalen, vorhergegangenen Exception auf, wovon ich aber nichts mitbekommen habe. Wieso fliegt da also ein Double Fault? Nichtmal die 2 Instruktionen, die nach dem setzen des Interrupt Enable Flags ausgeführt wurden konnten einen solchen Interrupt auslösen, weil es Sprünge zu sich selbst waren, um die CPU in einer Endlosschleife zu halten.</p>
<p>Kommen wir zurück zum Rattenschwanz: Nachdem ich dann die Interrupt Handler und die Verwaltung der IDT hatte, habe ich noch Routinen zur Verwaltung der <a href="http://de.wikipedia.org/wiki/Global_Descriptor_Table" target="_blank">GDT</a> implementiert. Es funktionierte immernoch nicht, was allerdings zu erwarten war, da es mehr eine Verzweifelungstat war als ein richtiger Lösungsansatz. Wir sind zu diesem Zeitpunkt bei Tag 3 des Kongresses.<br />
Allerdings war das ja auch nicht das Einzige, was ich da gemacht habe. Gab ja noch Vorträge.</p>
<p>Danach gings ans Debuggen. Ich habe VMware probiert, um zu sehen, was das Ding sagt. Wie erwartet: nichts. Es fehlen einfach die Debuggingmöglichkeiten unter Mac OS mit VMware.<br />
Dann gibts noch Qemu, an den man einen GDB klemmen kann. Gesagt getan. Nach wie vor nichts gefunden.<br />
Als letztes bin ich mit dem integrierten Debugger in Bochs dem Kram zu Leibe gerückt, mit dem man seinen Code auf Assemblerebene Debuggen konnte. Auch hier habe ich wieder nichts gefunden.</p>
<p>Was war das Ende vom Lied? Es gibt einen extra Chip auf x86 Systemem, der externe Interrupts handlet. Früher war das der <a href="http://de.wikipedia.org/wiki/Programmable_Interrupt_Controller" target="_blank">PIC (Programmable Interrupt Controller)</a> und heute ist es der <a href="http://de.wikipedia.org/wiki/APIC" target="_blank">APIC (Advanced Programmable Interrupt Controller)</a>, der auch Mehrprozessorsysteme ohne Gefrickel unterstützt.<br />
Diese Chips kann man so konfigurieren, dass jeder externe Interrupt (Tastatur, Floppy, Timer etc) auf einen der 256 Interrupts der CPU gemappt werden kann.</p>
<p>Irgendein Stück Software vor meinem Kernel hat genau das anscheinend mit dem Timerinterrupt gemacht und ihn auf Interrupt #8 gelegt.<br />
Das würde dann auch erklären, warum bei einem Double Fault eigentlich ein Errorcode auf den Stack gepusht werden sollte, was bei mir aber nie passiert ist. Es war schlicht und ergreifend kein Double Fault.</p>
<p>Also hab ich dann doch, entgegen meiner vorherigen &#8220;Brauchste eh nich&#8221;-Meinung, auch noch Code hinzugefügt, der den PIC (eigentlich sind es 2 PICs) entsprechend konfiguriert und die 16 Interrupts, die er verwalten kann, hinter die Exceptions mappt.</p>
<p>Was ist? Es funktioniert endlich.</p>
<p>Und so kann man sich wunderschön auf die Fresse legen und Zeit verbraten.<br />
Ich will nicht sagen ich hab nichts gelernt, genervt hat es aber doch schon ziemlich. Gedauert hat der ganze Prozess jetzt 6 Tage. Und ich hab immernoch keinen virtualisierten Code laufen.</p>
 <p>Feel free to Flattr this post at <a href="http://flattr.com/" title="Flattr" target="_blank">flattr.com</a>, if you like it.</p> <p><a href="http://flattr.com/" title="Flattr" target="_blank"><img src="http://www.geekatwork.de/wp-content/plugins/flattrss/button-compact-static-100x17.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekatwork.de/2010/01/03/systemprogrammierung/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>GeexOS</title>
		<link>http://www.geekatwork.de/projekte/geexos/</link>
		<comments>http://www.geekatwork.de/projekte/geexos/#comments</comments>
		<pubDate>Mon, 14 Dec 2009 00:26:44 +0000</pubDate>
		<dc:creator>Andy</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[GCC]]></category>
		<category><![CDATA[LD]]></category>
		<category><![CDATA[OS]]></category>
		<category><![CDATA[OSDev]]></category>

		<guid isPermaLink="false">http://galauner.de/wp/?page_id=5</guid>
		<description><![CDATA[Irgendwann, im Laufe eines Informatikstudiums, hört ma [...]]]></description>
			<content:encoded><![CDATA[<p>Irgendwann, im Laufe eines Informatikstudiums, hört man auch mal sowas ähnliches wie &#8220;Architektur von Rechnersystemen und Betriebsystemen&#8221;. Und da sich die dort vorgestellten Verfahren ja alle so einfach anhören und man sowas schon immer mal machen wollte, fängt man als Geek dann plötzlich an ein Betriebssystem zusammenzuhacken: Das GeexOS.</p>
<p>Wer jetzt schon heiß auf Code ist, kann ihn hier bekommen: <a href="http://github.com/G33KatWork/GeexOS" target="_blank">github</a></p>
<p>Die Architektur, die dieser Kernel haben soll, ist ein Mikrokernel. Bisher ist davon allerdings nicht viel implementiert, da ich mir seit ein paar Monaten versuche Gedanken über die Speicherverwaltung im Kernel zu machen und sowieso nicht immer Lust habe an diesem Projekt weiterzuarbeiten.</p>
<p>Aktuell Implementierte Features:</p>
<ul>
<li>Ein-/Ausgabe von Text über einen 80&#215;25 Zeichen Textmodus auf dem Monitor</li>
<li>Ein-/Ausgabe von Text über eine serielle Schnittstelle</li>
<li>Bootstrapping eines x86 Prozessors und Umgebung (Protected Mode, Interrupts, PIC, PIT)</li>
<li>Interrupthandling, welches bisher noch sehr Plattformabhängig ist</li>
<li>Ansätze eines HALs</li>
<li>Paging</li>
<li>Timer</li>
<li>Das Buildsystem, basierend auf GNU make</li>
</ul>
<p>Im master-Branch auf GitHub findet man noch einen implementierten Heap, den ich mitlerweile aber wieder weggeworfen habe, da ich ihn durch einen SLAB-Allocator mit etwas besserem Virtuellem Speichermanagement im Hintergrund ersetzen möchte.<br />
Eine weitere Designentscheidung, die ich im Züge des neuen Speichermanagements getroffen habe, ist das der Kernel auf einem 32 Bit System die vollen 32 Bit an virtuellem Speicher bekommen wird und nicht in den virtuellen Speicher eines jeden Prozesses eingeblendet wird. Dies geht zwar mit einem Performanceverlust einher, da ich bei jedem Systemaufruf oder Interrupt das Page Directory wechseln muss und somit der TLB (Translation Lookaside Buffer) geleert werden muss. Wie hoch dieser Verlust sein wird, weiß ich allerdings nicht. Mac OS X macht das auch so und das ist auch noch schnell.</p>
<p>Alle diese Änderungen befinden sich momentan im Branch 4gbKernel auf github.</p>
<p>Weitere geplante Features sind:</p>
<ul>
<li>Ein Scheduler mit Interprozesskommunikation über Shared Memory</li>
<li>Dieser Shared Memory kann auch auf anderen Rechnern liegen und das System kann somit verteilt werden</li>
<li>Einige Userspace System-Daemons, die Sachen wie das Prozessmanagement, Userspace Speicherverwaltung, Netzwerk, Dateisysteme etc. übernehmen</li>
<li>Einige Userspace Libs, die Posix implementieren, um GNU-Software ausführen zu können</li>
<li>Evtl. einen DOS-Kompatiblitätslayer</li>
</ul>
<p>Bis diese Sachen wirklich alle implementiert sind wird allerdings noch einiges an Zeit vergehen.</p>
<p><a rel="lightbox" href="http://www.geekatwork.de/wp-content/uploads/Bildschirmfoto-2009-12-18-um-20.58.00.png"><img class="alignnone size-medium wp-image-45" title="GeexOS 4gbKernel Branch" src="http://www.geekatwork.de/wp-content/uploads/Bildschirmfoto-2009-12-18-um-20.58.00-300x188.png" alt="GeexOS 4gbKernel Branch" width="300" height="188" /></a><br />
Screenshot des Aktuellen 4gbKernel-Branches in einem Qemu.</p>
<p><a rel="lightbox" href="http://www.geekatwork.de/wp-content/uploads/scheduling.png"><img class="alignnone size-medium wp-image-223" title="scheduling" src="http://www.geekatwork.de/wp-content/uploads/scheduling-300x188.png" alt="GeexOS Scheduler" width="300" height="188" /></a><br />
Screenshot mit kleinem Scheduler, der Kontextwechsel zwischen 2 Threads ausführt.</p>
<script type="text/javascript">
var flattr_wp_ver = '0.9.11';
var flattr_uid = 'G33KatWork';
var flattr_url = 'http://www.geekatwork.de';
var flattr_lng = 'en_GB';
var flattr_cat = 'text';
var flattr_tag = 'blog,wordpress,rss,feed';
var flattr_btn = 'large';
var flattr_tle = 'G33K @ Work';
var flattr_dsc = 'Basteleien eines Geeks';
</script>
<script src="http://api.flattr.com/button/load.js?v=0.2" type="text/javascript"></script> <p>Feel free to Flattr this post at <a href="http://flattr.com/" title="Flattr" target="_blank">flattr.com</a>, if you like it.</p> <p><a href="http://flattr.com/" title="Flattr" target="_blank"><img src="http://www.geekatwork.de/wp-content/plugins/flattrss/button-compact-static-100x17.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.geekatwork.de/projekte/geexos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
