{"title":"snaums.de","link":[{"@attributes":{"href":"https:\/\/www.snaums.de\/","rel":"alternate"}},{"@attributes":{"href":"https:\/\/www.snaums.de\/feed\/all.atom.xml","rel":"self"}}],"id":"https:\/\/www.snaums.de\/","updated":"2025-05-03T14:00:00+02:00","entry":[{"title":"Showtime! Chorkonzert aufnehmen.","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/fotografie\/showtime-chorkonzert-aufnehmen.html","rel":"alternate"}},"published":"2025-05-03T14:00:00+02:00","updated":"2025-05-03T14:00:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2025-05-03:\/fotografie\/showtime-chorkonzert-aufnehmen.html","summary":"<p>Ich singe in einem Chor, dem Jungen Chor Hannover (<a href=\"https:\/\/www.junger-chor-hannover.de\">Website<\/a>). Im Sommer 2024 haben wir ein Programm mit dem Titel Showtime in zwei Konzerten aufgef&uuml;hrt in dem wir einige St&uuml;cke aus bekannten Musicals dargeboten haben. Nat&uuml;rlich mit glitzerndem Show-Outfit, mit B&uuml;hnenbild, Beleuchtung und mit Choreographien. Das ist sehr viel Arbeit \u2026<\/p>","content":"<p>Ich singe in einem Chor, dem Jungen Chor Hannover (<a href=\"https:\/\/www.junger-chor-hannover.de\">Website<\/a>). Im Sommer 2024 haben wir ein Programm mit dem Titel Showtime in zwei Konzerten aufgef&uuml;hrt in dem wir einige St&uuml;cke aus bekannten Musicals dargeboten haben. Nat&uuml;rlich mit glitzerndem Show-Outfit, mit B&uuml;hnenbild, Beleuchtung und mit Choreographien. Das ist sehr viel Arbeit f&uuml;r alle Beteiligten gewesen, weshalb auch die Idee aufkam die Konzerte festzuhalten. Deshalb, und keinesfalls weil ich mir das Tanzen-Lernen ersparen wollte, habe ich mir diese Aufgabe angenommen und habe die beiden Konzerte mit Kameras zu begleitet. Ziel war es auch das Konzert dann dem regionalen B&uuml;rger*innenfernsehsender h1 (<a href=\"https:\/\/www.h-eins.tv\">Website<\/a>) zur Verf&uuml;gung zu stellen. Das Video gibt es auch online:<\/p>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=KZTMsFaNFog\">Showtime: Ein Hauch von Broadway. (Youtube)<\/a><\/p>\n<p>In diesem Blogpost will ich einmal darstellen, wie ich vorgegangen bin und was ich f&uuml;r k&uuml;nftige Aufnahmen gelernt habe. Nat&uuml;rlich war ich nicht alleine, sondern wurde von 3 Kameraleuten unterst&uuml;tzt.<\/p>\n<h2 id=\"aufbau\">Aufbau<\/h2>\n<p>Der Konzertraum war eine Aula einer Schule in Hannover, ein relativ breiter Raum mit 2 Bl&ouml;cken an St&uuml;hlen getrennt von einem Gang nach vorn zur B&uuml;hne. Es gibt eine feste aber verschiebbare Beleuchtung, die ein Sch&uuml;ler der Schule bedient hat. Das gesamte Programm findet auf der B&uuml;hne statt. Der Chor stand zentral, links daneben war eine kleine Band aus einem Pianisten, einem Bassisten und einem Drummer aufgebaut.<\/p>\n<p>Wir haben 3 Kameras verwendet, konkret Sony Sony PXW-X70, 2 davon standen ganz hinten gerade zur B&uuml;hne ausgerichtet (die habe ich K1 und K3 genannt). K2 steht rechts neben dem Publikumsblock, relativ nach zur B&uuml;hne. K1 und K2 haben wir eher f&uuml;r Mittelnahaufnahmen verwendet, wo einzelne Personen oder Stimmgruppen im Bild sein sollten. K3 sollte immer den gesamten Chor im Bild halten. K3 hatte ein defektes Einstellrad, musste also sowieso im Automodus verwendet werden. Die Kamera entschied also sowieso &uuml;ber die Belichtung -- trifft sich also eigentlich ganz gut dass die Kamera ein recht statisches Bild liefert. Alle Kameras waren auf Stative montiert und blieben dort &uuml;ber das gesamte Konzert. Die Kamera waren etwas &uuml;ber Kopfh&ouml;he.<\/p>\n<p>Diese speziellen Kameras haben zwei Aufnahmemodus AVCHD und XAVC. Wir haben bei der Generalprobe herausgefunden dass diese Kameras in XAVC erstmal alle Audioquellen einzeln aufnehmen, mehr Bitrate liefern und nicht in 4GB gro&szlig;e Dateien splitten, in AVCHD aber schon. Da wir Techniker sind und auf gro&szlig;e Zahlen stehen, wollen wir nat&uuml;rlich maximale Qualit&auml;t und haben in XAVC aufgenommen. Bei der Generalprobe haben wir uns auch Werte f&uuml;r den Wei&szlig;abgleich ausgesucht und grobe Werte f&uuml;r die Blenden und Shutterspeed herausgefunden, die wir beim Konzert benutzen k&ouml;nnten.<\/p>\n<p>Bei diesem Dreh ist der Abstand zum Chor konstant, also macht es Sinn einmal entweder manuell oder automatisch den Fokus zu ziehen und dann zu sperren oder auf manuell umzustellen. Die Kameras k&ouml;nnen zwar Autofokus, wenn die aber aus irgendeinem Grund den Punkt verlieren und wir dann st&auml;ndig Fokusbreathing im Material haben ist das eher unsch&ouml;n. Insbesondere die hinteren beiden Kameras haben wir im manuellen Fokus betrieben und nur ganz zum Schluss am Fokusring gedreht.<\/p>\n<p>Wir haben 3 Mikrofone an die Kameras angeschlossen, 2 davon an K2, die Kabel haben wir an die Stufen der B&uuml;hne gelegt. Diese beiden Mikrofone haben wir recht weit rechts und links vor die B&uuml;hne gestellt. Die Hoffnung war, dass wir damit einzelne Stimmgruppen gesondert auf die Aufnahmespuren bekommen, das hat halbwegs geklappt. Ein weiteres Mikrofon haben wir in die Mitte, leicht neben dem Chorleiter gestellt und an eine der Kameras hinten angeschlossen. Der Chor selbst nimmt die eigene Konzerte selbst mit einem Zoom-Recorder auf, der etwa in der Mitte des Publikumsblocks stand.<\/p>\n<p>Der Aufbau hat recht gut funktioniert. K1 und K2 haben sehr verschiedene Bildausschnitte geliefert, besonders bei Moderationen. K1 und K3 haben manchmal zu &auml;hnliche Bilder aufgezeichnet, insbesondere am Ende von St&uuml;cken oder beim abschlie&szlig;enden Applaus wenn K1 weit rausgezoomt war.<\/p>\n<p>Das Equipment hat wie abgemessen in ein Lastenrad von <a href=\"https:\/\/www.hannah-lastenrad.de\/\">Hannah<\/a> gepasst, das ist ein Lastenrad-Leihdienst vom ADFC. :D<\/p>\n<div class=\"content thumb-full\" style=\"height:350px;background-image:url('\/data\/thumbnail\/jch-showtime-hannah_large.jpg')\"><div class=\"thumbnailed_headline\"><a href=\"\/data\/thumbnail\/jch-showtime-hannah_full.jpg\" target=\"_blank\">Hannah Lastenfahrrad voller Kameras und Stative<\/a><\/div><\/div>\n<h2 id=\"bearbeitung\">Bearbeitung<\/h2>\n<p>Nach den Konzerten hatte ich dann insgesamt etwa 8 Stunden Material: 2 Konzerte, 3 Kameras, jeweils etwas &uuml;ber 1 Stunde Material. Wie bearbeitet man das jetzt?<\/p>\n<p>Es gibt viele Programme zum Bearbeiten von Videos, ich habe mich f&uuml;r KDEnlive entschieden, ein freier, open-source nicht-linearer Videoeditor. KDEnlive hat die positive Eigenschaft, dass es einerseits quasi alle Formate, die ffmpeg versteht, importieren kann, es kann Proxy-Clips, also heruntergerechnete Clips zur schnelleren Bearbeitung, erzeugen und hat einen Multi-Cam Modus, bei dem man alle Spuren gleichzeitig gezeigt bekommt und durch Zahlentasten aussuchen kann, welcher Feed im fertigen Projekt landen soll.<\/p>\n<p>Seid nun so schlau und erstellt, anders als ich, ein Projekt mit Stereo Audioausgabe. Ich hatte mich f&uuml;r ein 5.1 Audiosetup entschieden und keine M&ouml;glichkeit gefunden das zu &auml;ndern wenn das Projekt einmal aufgebaut ist. F&uuml;rs Fernsehen reicht Stereo problemlos aus, es sei denn ihr wisst genau was ihr da tut. Jetzt bekam ich aber nur Video mit 5.1 Audio aus dem Programm, was immer etwas komisch klang. Ich habe das dann mit Audacity und ffmpeg gel&ouml;st, aber das hatte eine Menge unsch&ouml;ne Nebeneffekte.<\/p>\n<p>Aber erstmal die Videos importieren. Jetzt kann man &uuml;berlegen ob man direkt Proxy-Clips anschaltet, damit die Bearbeitung fl&uuml;ssiger abl&auml;uft oder ob man den Grobschnitt mit voller Aufl&ouml;sung machen will. Dann sollte der Rechner aber gut genug sein. Ich empfehle euch die Videos gut zu sortieren -- pro Aufnahmetag und am besten auch nach Kamera wenn ihr mehrere Clips habt. Nun kommt der schwierige Teil -- die Videos zu synchronisieren.<\/p>\n<p>Am einfachsten ist es, wenn wir ein lautes, kurzes Ger&auml;usch haben, um die Videos zu synchronisieren -- im Idealfall sowohl im Audio als auch auf der Videospur. Dieses Ger&auml;usch, bspw. ein Klatschen, k&ouml;nnen wir dann benutzen um die Peaks im Audio direkt &uuml;bereinanderzulegen. Wenn nun das Ger&auml;usch genau beim Zusammenschlagen der H&auml;nde kommt, haben wir die Videos korrekt synchronisiert. Das habe ich nicht gehabt, also musste ich mir andere Ger&auml;usche suchen, und dann die Audiospuren immer wieder einzeln anschalten um zu sehen dass sie wirklich aufsynchronisiert sind. Beim n&auml;chsten Mal, werde ich ein Synchronisationsklatschen verwenden.<\/p>\n<h3 id=\"schnitt\">Schnitt<\/h3>\n<div class=\"content thumb-full\" style=\"height:450px;background-position-y:-50px;background-image:url('\/data\/thumbnail\/jch-showtime-kdenlive_large.png')\"><div class=\"thumbnailed_headline\"><a href=\"\/data\/thumbnail\/jch-showtime-kdenlive_full.png\" target=\"_blank\">KDEnlive Projektansicht<\/a><\/div><\/div>\n<p>Alle drei Clips sollten &uuml;bereinander liegen, dann kann &uuml;ber Werkzeug -&gt; Multikamera Werkzeug in die Multicam-Anzeige umgeschalten werden. Jetzt sehen wir die drei Videofeeds im Projektmonitor. Dr&uuml;cken wir nun 1, 2 oder 3 schalten wir zwischen den Spuren um. KDEnlive setzt das so um, dass alle anderen Spuren dabei ausgeschnitten werden, seit dem letzten Schnitt. Das ist eine nette L&ouml;sung, hat aber den Nachteil, dass ihr sehr viele kleine Clips (zum Gl&uuml;ck auf ihren eigenen Spuren) habt. Mit dem Multikamera Werkzeug kann der Grobschnitt recht problemlos gemacht werden. Nat&uuml;rlich machen wir hierbei Fehler oder das Timing stimmt nicht ganz genau. Wir m&uuml;ssen ohnehin noch ein paar mal &uuml;ber das Projekt dr&uuml;bergehen und genauer schneiden oder Belichtung anpassen.<\/p>\n<p>Beim Grobschnitt habe ich mir mit Hilfslinien Notizen gemacht -- wo beginnt welches Lied, wo ist Moderation, etc. Jetzt kommen 1-2 Durchg&auml;nge des genauen Anpassens. Hier geht es darum Cuts richtig auszurichten. Ich habe mich versucht am Takt der Musik auszurichten. Achtet unbedingt darauf die Clips nicht zu verschieben, sondern erst nach vorne\/hinten zu verl&auml;ngern, und dann zu verkleinern, damit KDEnlive die richtige Videostelle rauskramt.<\/p>\n<p>Ich habe hier zun&auml;chst beide Konzerte angeschaut und grobgeschnitten. Theoretisch w&auml;re es so m&ouml;glich gewesen ein Lied was bei einem Konzert nicht geklappt hat, durch das vom Anderen auszutasuchen. Davon abgesehen dass das auff&auml;llt, habe ich das nicht gemacht, weil am Sonntag quasi alles ohnehin besser war. Au&szlig;erdem macht das in diesem Setup massenhaft Arbeit, denn auch die Audiospuren wollen sauber eingef&uuml;gt werden, was nicht immer einfach ist. Am Ende habe ich mich nach dem Grobschnitt f&uuml;r den Sonntag entschieden, und den anderen Drehtag abgeschrieben.<\/p>\n<h3 id=\"audio\">Audio<\/h3>\n<div class=\"content thumb-full\" style=\"height:300px;background-image:url('\/data\/thumbnail\/jch-showtime-audacity_large.png')\"><div class=\"thumbnailed_headline\"><a href=\"\/data\/thumbnail\/jch-showtime-audacity_full.png\" target=\"_blank\">Audacity Projektansicht<\/a><\/div><\/div>\n<p>Bislang habe ich mich haupts&auml;chlich mit dem Video besch&auml;ftigt. Ich habe mich nach dem Schneiden daf&uuml;r entschieden die Audiospuren externn in Audacity bearbeiten zu wollen. KDEnlive bietet grundlegende Features um Audio zu bearbeiten, es gibt einen einfachen Mixer und es gibt ein paar Filter und Effekte, aber am Ende habe ich deutlich mehr gemacht. Und durch den Fehler mit dem 5.1 Projekt blieb mir eigentlich auch keine andere Wahl mehr. Um keine Verluste durch Komprimierung zu haben, habe ich die Audiospuren in KDEnlive einzeln nach FLAC exportiert und dann in Audacity importiert. FLAX ist ein Format, was verlustfrei komprimiert, d.h. das Audiosignal bleibt beim Abspeichern vollst&auml;ndig erhalten. Die Audiodateien sollten im Audacity aufeinanderpassen. Hier m&uuml;ssen wir uns aber sicher sein, dass wir nichts am Video mehr schneiden wollen -- sonst haben wir ein riesiges Problem.<\/p>\n<p>Nun geht es erstmal darum die Mikrofone richtig abzumischen. Wo stand welches Mikrofon, welche Spur ist rechts, welche links? Wir hatten links ein Piano stehen, sodass auch im Audio leicht links das Piano st&auml;rker durch kommen sollte, und die linkeren Mikros das Piano lauter aufgenommen haben. Ich habe die Mikros ganz vorn an der B&uuml;hne auf 100% links und 100% rechts gestellt, und den Zoom-Recorder auf 40% links\/40% rechts. Das Mikrofon mittig vorn an der B&uuml;hne war leider zu stark &uuml;bersteuert (passt auf eure Mikrofon-Einstellungen auf!), sodass ich das nur f&uuml;r Soli benutzt habe, um die Solist*innen besser aus dem Chor rauszuholen.<\/p>\n<p>Dann geht es weiter zur Bearbeitung des Audios. Die Moderationen waren bei mir recht leise, die habe ich verst&auml;rkt. Geht der Applaus los, bevor die Moderation endet, muss abgewogen werden, ob es wichtiger ist den Satz zu verst&auml;rken oder dass der Applaus nicht zu laut wird. Eventuell wurde der Satz ohnehin danach neu angefangen, dann k&ouml;nnen wir die Moderation vom Applaus auch verschlucken lassen. Daf&uuml;r waren einige St&uuml;cke etwas zu laut, die habe ich verringert. Wichtig war, dass beim abschlie&szlig;enden Mischen keine Stellen &uuml;brig bleiben, die Clippen, also aus dem maximalen Bereich herausreichen, dann entstehen unangenehme Kratzger&auml;usche.<\/p>\n<h3 id=\"zusammenfuhren\">Zusammenf&uuml;hren<\/h3>\n<p>Durch meinen kleinen Fehler am Anfang musste ich das Audio nachtr&auml;glich auf das Video legen. Ich habe im KDEnlive auch nicht genau bei 0 angefangen, also habe ich sowohl im KDEnlive, als auch im Audacity einen Teilbereich markiert und nur den Teilbereich exportiert.<\/p>\n<p>Dann mithilfe von ffmpeg das exportierte FLAC aus Audacity auf das Video aus KDEnlive gelegt, dabei das originale Audio ersetzt. Das geht relativ schnell (in meinem Fall in 20-facher Geschwindigkeit), weil das Video nicht neu einkodiert werden muss. Wichtig ist dann, genau hinzuschauen ob das Audio synchron ist.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>ffmpeg<span class=\"w\"> <\/span>-i<span class=\"w\"> <\/span>video.mp4<span class=\"w\"> <\/span>-i<span class=\"w\"> <\/span>new_audio.flac<span class=\"w\"> <\/span>-c:v<span class=\"w\"> <\/span>copy<span class=\"w\"> <\/span>-map<span class=\"w\"> <\/span><span class=\"m\">0<\/span>:v:0<span class=\"w\"> <\/span>-map<span class=\"w\"> <\/span><span class=\"m\">1<\/span>:a:0<span class=\"w\"> <\/span>c:a<span class=\"w\"> <\/span>aac<span class=\"w\"> <\/span>-b:a<span class=\"w\"> <\/span>320k<span class=\"w\"> <\/span>output.mp4<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"probeschauen\">Probeschauen<\/h3>\n<p>Ganz zum Schluss habe ich mehrfach &uuml;ber das fertige Video dr&uuml;bergeschaut, auch in verschiedenen (ok, 2) Soundsetups und ich habe es auch dem Chor gegeben zum Probeschauen. Hier geht es darum Fehler zu finden. Wo sitzt der Schnitt nicht korrekt. Gibt es Bilder nicht schwarz sind, gibt es welche die zu dunkel\/zu hell sind? Gibt es welche die nicht h&uuml;bsch sind und ausgetauscht werden k&ouml;nnten? Passen die &Uuml;berblendungen?<\/p>\n<h2 id=\"learnings_1\">Learnings<\/h2>\n<p>Was habe ich am Ende also gelernt?<\/p>\n<h3 id=\"absprachen-sind-wichtig-besonders-bei-der-belichtung\">Absprachen sind wichtig, besonders bei der Belichtung<\/h3>\n<p>Wenn man durch das Video durchschaut sieht man dass K1 manchmal etwas zu dunkel ist, die anderen Kameras aber meistens ein relativ gutes Bild liefern. Zugegeben waren die Lichtverh&auml;ltnisse f&uuml;r die Kameras schwierig, einige S&auml;nger*innen sind sehr hell beleuchtet, einige standen eher im Schatten.<\/p>\n<p>Gute Absprachen machen hier aber das Leben des Cutters einfacher -- welche Belichtung stellen wir ein, damit halbwegs vergleichbare Bilder rauskommen. Da eine der Kameras nur auf Auto laufen konnte, h&auml;tten wir die Belichtungseinstellungen einfach den Kameras &uuml;berlassen k&ouml;nnen, dann w&auml;ren recht vergleichbare Bilder rausgekommen. Haben wir aber nicht. Dann mussten einige Stellen halt nachtr&auml;glich angehoben werden, was zum Gl&uuml;ck nicht so sehr auff&auml;llt, aber es ist einfach Arbeit, die man sich sparen k&ouml;nnte. Und dann muss es &uuml;berall gemacht werden.<\/p>\n<p>Idealerweise k&ouml;nnte man das per Intercom absprechen, oder man m&uuml;sste sich die Einstellungen festlegen, was wieder das Potential hat, dass die Einstellungen nicht passen, wenn sich das Licht &auml;ndert.<\/p>\n<p><strong>Video ist kein Foto<\/strong>. Beim Fotografieren belichtet man eher etwas unter \"expose to the right\". Dabei geht es darum, dass im Histogram keine Pixel ganz wei&szlig; sind, dann ist die Information in den Details dieser Bildstellen komplett verloren. Schatten holt man meist recht gut aus den RAW-Dateien in der Nachbearbeitung heraus, weil noch recht viel Information auch in dunklen Stellen gespeichert ist (insbesondere bei 14 Bit Aufnahmen), komplett wei&szlig; Pixel, also &uuml;berbelichtete Pixel enthalten aber keine Details mehr, die man retten k&ouml;nnte.<\/p>\n<p>Video ist aber kein Foto. Au&szlig;er ihr habt gute Cine-Kameras, werden direkt komprimierte Videos aufgenommen. Wir haben die Kameras auf eine hohe Bitrate eingestellt, aber dennoch ist es komprimiert und auch nicht mit 14 Bit Farbtiefe. Ein paar Stufen kann man sicher hochziehen -- das musste ich am Ende sogar, aber das geht nicht unendlich weit. Deshalb solltet ihr versuchen eher \"mittig\" zu belichten. Dann sind halt ein paar Stellen wei&szlig;, das ist meist zu verkraften, mehr jedenfalls als wenn das Bild einfach zu dunkel wird. Insbesondere wenn kein Film gedreht wird, sondern \"nur\" ein Livekonzert f&uuml;rs Fernsehen aufgenommen wird, macht es mehr Sinn direkt Bilder aufzunehmen die sendbar sind.<\/p>\n<h3 id=\"eure-einstellungen-genau-betrachten\">Eure Einstellungen genau betrachten<\/h3>\n<p>Dass das Mikrofon vorne mittag an der B&uuml;hne deutlich zu laut war, ist eindeutig mein Fehler. Hier habe ich vergessen nochmal auf die Audio-Ausschl&auml;ge zu schauen und nachzukorrigieren. Am Ende ist das hier nicht kritisch gewesen und eventuell sogar ganz gut, so konnten die Solist*innen besser verst&auml;rkt werden, aber es h&auml;tte problematisch sein k&ouml;nnen. Plant also genug Back-up ein, dass ihr auch mal was verkacken k&ouml;nnt und dann trotzdem noch ein Video habt.<\/p>\n<h3 id=\"totale-sind-kein-allheilmittel\">Totale sind kein Allheilmittel<\/h3>\n<p>Vor der Aufnahme habe ich mir die K3 als Backup vorgestellt - die Kamera nimmt sowieso eine Totale auf, da ist alles drauf, falls K1 und K2 mal kein brauchbares Bild liefern. Das stimmt manchmal, aber manchmal auch nicht. Wenn die Kameras zu &auml;hnliche Bilder liefern, ist ein Schneiden von K1 auf K3 eher h&auml;sslich. Zu lange auf der Totalen zu bleiben wirkt auch ziemlich langweilig und undynamisch. Hier kann man das sogar noch fast verkraften, weil man dann wenigstens die ganze Choreo sieht.<\/p>\n<p>Und an einer Stelle stand jemand direkt vor K1 und K3 auf, was nat&uuml;rlich die Shots ruiniert hat. H&auml;tten wir das vermeiden wollen, h&auml;tten wir die Kameras h&ouml;her stellen m&uuml;ssen und ggf. weiter auseinander.<\/p>\n<h2 id=\"fazit_1\">Fazit<\/h2>\n<p>Am Ende war das haufenweise Arbeit, auch weil ich beim Aufnehmen mir nicht genug Gedanken gemacht habe oder bestimmte Dinge einfach nicht beherzigt habe. Dennoch ist ein sehr h&uuml;bsches Video rausgekommen, auf das ich auch sehr stolz bin. Am Ende habe ich knapp 4,5 Monate gebraucht bis das Video fertig war. Das ist nicht mein Vollzeitjob und so bleiben halt nur noch Wochenende an denen man mal Lust darauf hat. Insgesamt eine Zeitspanne die vertretbar ist, zumal wir ja keinen Zeitdruck in der Nachbearbeitung gehabt haben.<\/p>\n<p>Abschlie&szlig;end danke an meine Kameraleute. Und nat&uuml;rlich an den Chor, der das Experiment mitgemacht hat :D<\/p>","category":[{"@attributes":{"term":"Fotografie"}},{"@attributes":{"term":"chor"}},{"@attributes":{"term":"showtime"}},{"@attributes":{"term":"junger chor hannover"}},{"@attributes":{"term":"aufnehmen"}},{"@attributes":{"term":"tv"}},{"@attributes":{"term":"fernsehen"}},{"@attributes":{"term":"h1"}},{"@attributes":{"term":"hannover"}},{"@attributes":{"term":"kamera"}},{"@attributes":{"term":"video"}},{"@attributes":{"term":"konzert"}}]},{"title":"Catching Native Crashes under JNI with UNIX Signals","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/jni-catching-native-crashes-with-unix-signals.html","rel":"alternate"}},"published":"2023-12-31T17:00:00+01:00","updated":"2023-12-31T17:00:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2023-12-31:\/informatik\/jni-catching-native-crashes-with-unix-signals.html","summary":"<p>A while back I've written about the Java Native Interface (JNI) and how to use and abuse it for running native code inside your Java program, either to run legacy code or to have performance critical code run natively. However if your native code crashes, which is not that hard \u2026<\/p>","content":"<p>A while back I've written about the Java Native Interface (JNI) and how to use and abuse it for running native code inside your Java program, either to run legacy code or to have performance critical code run natively. However if your native code crashes, which is not that hard in C\/C++, then it takes your Java program with it. If your Java program is a server applet running inside a Tomcat process for example, your whole webserver comes crashing down and a world of pain is waiting for you.<\/p>\n<p>A friend of mine had quite a clever \"solution\" to this problem, at least on Linux. While, we would like to eliminate all sources of crashes forever, this is not possible and unrealistic, we can however make debugging a bit easier. We would like to:<\/p>\n<ol>\n<li>catch a crash,<\/li>\n<li>write a crashdump (or at least backtrace) for easier debugging,<\/li>\n<li>throw an exception into the Java-world so it can try and shut down gracefully.<\/li>\n<\/ol>\n<p>But first we will have to learn a few basics about Linux and Unix. And if you've missed the first JNI-article and are missing a few of the essentials, feel free to read that first.<\/p>\n<h2 id=\"fundamentals-about-unix-signals\">Fundamentals about UNIX signals<\/h2>\n<p>Unix signals are a way in the Operating System to transfer data into a process. This is used to stop or pause a process (SIGSTOP), to notify a debugger about changes in the child process (SIGCHILD) or even to kill a process (SIGTERM, SIGKILL). Also the operating system stops a process and sends it a Signal when the process tried to execute an illegal instruction (SIGILL), tried to access invalid memory locations (SIGSEGV) or a bus error occured (SIGBUS). There is even a signal when the terminal changes in size (SIGWINCH).<\/p>\n<p>Whenever a process receives such a signal, there is an action associated with it. A process may mask (i.e. disable) a signal, so it will be ignored, when it receives the signal, take the default action (which is to ingore the signal for most of them), or handle the signal itself. Afterall, most signals can just be caught, handled and the program wouldn't necessarily need to abort execution, in some cases aborting is the only reasonable way forward; with SIGTERM it is the only way to go (it cannot be caught).<\/p>\n<p>Let's assume a C program like this. We have a main routine, where we set a pointer into some memory, and write to it in a loop.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdint.h&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"w\"> <\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint8_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">ptr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"mh\">0x400000000000<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"o\">&lt;<\/span><span class=\"mi\">8192<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"o\">++<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"o\">*<\/span><span class=\"n\">ptr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">3<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">ptr<\/span><span class=\"o\">++<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Trying it out, we will receive a SIGSEGV (Segmentation Fault), the exact output could depend on your shell:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>gcc<span class=\"w\"> <\/span>main.c<\/code><\/span>\n<span class=\"code-line\">$<span class=\"w\"> <\/span>.\/a.out<\/span>\n<span class=\"code-line\">fish:<span class=\"w\"> <\/span>Job<span class=\"w\"> <\/span><span class=\"m\">1<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">'.\/a.out'<\/span><span class=\"w\"> <\/span>terminated<span class=\"w\"> <\/span>by<span class=\"w\"> <\/span>signal<span class=\"w\"> <\/span>SIGSEGV<span class=\"w\"> <\/span><span class=\"o\">(<\/span>Segmentation<span class=\"w\"> <\/span>Fault<span class=\"o\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Nothing unexpected here. Clearly the 0x4... pointer points into virtual memory, that was not mapped to the process. Writing to it will cause the processor to trap into a page fault handler, where the operating system checks the address. It will look in its internal data structure and map memory to the place, if it sees that there should be something mapped (see lazy paging or the growing stack). If there is nothing mapped, a SIGSEGV signal is sent to the offending process. The default behaviour of SIGSEGV is to abort program execution.<\/p>\n<p>But we can overwrite the default action and define our own with [<a href=\"https:\/\/man.archlinux.org\/man\/sigaction.2\">sigaction<\/a>]. If we set a signal handler for the SIGSEGV signal and map new memory into the space we just wanted to access, similar to [<a href=\"https:\/\/www.ibr.cs.tu-bs.de\/users\/dietrich\/advent\/06-sigaction\/\">advent(2)<\/a>], then we will be able to run our program to completion. This is just an example of what we can do. Trying this in production <strong>will<\/strong> break things, and you should never ever just ignore a SIGSEGV. While we are purposely writing into some random memory, most programs will trash the stack, heap or other necessary data, way before jumping into random memory.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ Have a look here: https:\/\/osg.tuhh.de\/Advent\/06-sigaction\/<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdint.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdlib.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdio.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;string.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;signal.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;unistd.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/types.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/mman.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PAGE_SIZE 4096<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">sa_sigsegv<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">signum<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">siginfo_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">info<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">context<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ Calculate the page address from the fault address<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ 0xdeadbeef -&gt; 0xdeadb000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uintptr_t<\/span><span class=\"w\"> <\/span><span class=\"n\">addr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">uintptr_t<\/span><span class=\"p\">)<\/span><span class=\"n\">info<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">si_addr<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">addr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">addr<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">~<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">PAGE_SIZE<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ MMAP one page of anonymous private memory to that location.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ Afterwards, the program can continue its way to perdition.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ret<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mmap<\/span><span class=\"p\">((<\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"n\">addr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">PAGE_SIZE<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                     <\/span><span class=\"n\">PROT_READ<\/span><span class=\"o\">|<\/span><span class=\"n\">PROT_WRITE<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                     <\/span><span class=\"n\">MAP_PRIVATE<\/span><span class=\"o\">|<\/span><span class=\"n\">MAP_ANONYMOUS<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                     <\/span><span class=\"mi\">-1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">ret<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"n\">MAP_FAILED<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">perror<\/span><span class=\"p\">(<\/span><span class=\"s\">\"mmap\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">exit<\/span><span class=\"p\">(<\/span><span class=\"mi\">-1<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"w\"> <\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">sigaction<\/span><span class=\"w\"> <\/span><span class=\"n\">sa<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">memset<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"n\">sa<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_flags<\/span><span class=\"w\">     <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_SIGINFO<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_RESTART<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_sigaction<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa_sigsegv<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sigemptyset<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_mask<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">sigaction<\/span><span class=\"p\">(<\/span><span class=\"n\">SIGSEGV<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">perror<\/span><span class=\"p\">(<\/span><span class=\"s\">\"sigaction\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">-1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint8_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">ptr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"mh\">0x400000000000<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"o\">&lt;<\/span><span class=\"mi\">8096<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"o\">++<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"o\">*<\/span><span class=\"n\">ptr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">3<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">ptr<\/span><span class=\"o\">++<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"a-caveat\">A Caveat<\/h3>\n<p>Some of you reading this, will scream at the piece of code above. A signal handler can be called by the OS <em>at any time<\/em>, so we have no information about locks that are held or the state of other threads. They could be in the kernel right now, trying to allocate memory or may be altering important global data structures.<\/p>\n<p>Make no mistake, we are trying to do something useful in a Unix signal handler, which it is not there for. There are several sources warning developers about doing anything more than setting a global flag (and even that might be racey). Accessing global data is tabu, executing asynchronous calls, that could use locks internally is tabu. Let's just say, everything fun should not be avoided in signal handlers.<\/p>\n<p>What we are about to do works for my friend, but it most definitely might not work for you. It is based on undefined behaviour, which might lead to nothing bad hapenning at all, random signals or crashes, subtle behavioural changes or nasal daemons.<\/p>\n<h2 id=\"what-we-want-to-achieve_1\">What we want to achieve<\/h2>\n<p>The above example shows a use case for a signal handler (ignoring the quite obvious warnings about signal handlers). Most of the times, SIGSEGV should not be overwritten, or if so only to print some more information (which is still undefined behaviour). Some signals, like SIGSEGV indicate a program error, that cannot be recovered from. When you receive SIGSEGV you cannot be certain, that all the process' memory is intact.<\/p>\n<p>However. We want to run a Java-program, that links to native code via the Java Native Interface (JNI). The scenario is, that we have a library of legacy code, that cannot easily be ditched or rewritten in Java, so for the time being we will need to run this unsafe code and shield it, as good as we can, from potentially malicious user input.<\/p>\n<p>Unsafe native code can however still crash. In C or C++ it is easy to forget the lifetime of your objects, forget to check a pointer for null or to ensure, that the object you want to call is the object you are trying to call. Java protects you from some of these errors with its type safety approach and garbage collection.<\/p>\n<p>But, anyway. Your native code could crash, it could bring down your whole Java process with it. Remember, if we catch a SIGSEGV signal and if we don't handle it (assuming the Java JVM doesn't gracefully ignore it), the whole process is aborted, include everything that runs inside it, if that is a whole Tomcat webserver, it will come down as well. Very ungraceful.<\/p>\n<p>So, let's try and catch the crash, gather some information and maybe even let our Java program catch an Exception and shut down somewhat gracefully.<\/p>\n<h3 id=\"glueing-it-back-together\">Glueing it back together<\/h3>\n<p>In my previous article we've set up a thin wrapper glue library, that is actually loaded by the Java VM, converts parameter types and jumps into our native C\/C++ code. Who says we can't use this library to have some fun?<\/p>\n<p>Firstly, we will need a signal handler. This is were this mechanism could become quite unstable: the Java Virtual Machine uses signals itself, so overwriting or chaining signal handlers the wrong way can break (future versions) of our Java program, so I wouldn't recommend this approach to use in production. You've been warned.<\/p>\n<p>But still, let's write ourselves a signal handler in our glue-library, that gathers a crash log, prints it to stderr and exits:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">SignalHandler<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">signum<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">siginfo_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">si<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">uc<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Signal \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">signum<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\" (SIG\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">sigabbrev_np<\/span><span class=\"p\">(<\/span><span class=\"n\">signum<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\")\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">void<\/span><span class=\"o\">**<\/span><span class=\"w\"> <\/span><span class=\"n\">buffer<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">malloc<\/span><span class=\"p\">(<\/span><span class=\"mi\">64<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">num<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">backtrace<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">buffer<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">64<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">backtrace_symbols_fd<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">buffer<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">num<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">STDERR_FILENO<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">abort<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"nf\">JNI_OnLoad<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">JavaVM<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">vm<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">res<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">sigaction<\/span><span class=\"w\"> <\/span><span class=\"n\">sa<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">memset<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"n\">sa<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_flags<\/span><span class=\"w\">     <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_SIGINFO<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_RESTART<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_sigaction<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">SignalHandler<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sigemptyset<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_mask<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">sigaction<\/span><span class=\"p\">(<\/span><span class=\"n\">SIGSEGV<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"[FATAL] sigaction failed\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">-1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">JNI_VERSION_1_2<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We've created an oddly looking function, JNI_OnLoad. This function is called by Java, when the library is loaded. It is there to initialize the native library; many C libraries need to call an initializer function for preparing internal data structures before doing anything useful. We use it to register a signal handler. A similar function exists for Unloading a library, see [<a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/jni\/spec\/invocation.html\">Java: Invocation API<\/a>];<\/p>\n<p>But are we actually registering a signal handler though? If we read a bit more of the JVM docs, we will find [<a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/17\/troubleshoot\/handle-signals-and-exceptions.html#GUID-F012840D-8E5A-4B6D-8E49-0129A9EE46DB\">Java: Signal Handling<\/a>] and [<a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/17\/vm\/signal-chaining.html\">Java: Signal Chaining<\/a>]. If we just try to use this piece of code and not bother with anything else, our Java program will crash occasionally, for example when some NullPointer Exceptions would be thrown, or maybe when new objects will be allocated. That's no fun.<\/p>\n<p>The JVM uses Unix Signals to detect null pointer accesses and uses those to generate a NullPointer Exception. It also uses Unix Signals to \"automatically\" grow Java stacks. We've just overwritten a used Signal Handler of our JVM, so we're hindering the JVM to do its job.<\/p>\n<p>The JVM has a facility to catch Signals, that the JVM doesn't know what to do with: Signal Chaining. If we preload <code>libjsig.so<\/code>, it will overwrite calls like <code>sigaction<\/code>. This way and call to <code>sigaction<\/code> is intercepted, it stores our signal handler internally. If the JVM catched a signal, that it cannot do anything useful with in it own handlers, it will call (chain) our signal handler behind it's own. <\/p>\n<p>This behaviour includes some SIGSEGV errors (some are caught by JVM to implement an auto growing stack). This also means, we have no control over the real signal handler, but we can execute code, if signals are caught.<\/p>\n<p>To preload <code>libjsig.so<\/code>, so we'll load it <strong>before<\/strong> the libc, which would set <code>sigaction<\/code> itself, we need to invoke our program with the LD_PRELOAD (see [<a href=\"https:\/\/man.archlinux.org\/man\/core\/man-pages\/ld.so.8.en\">ld.so<\/a>]) environment set:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>LD_PRELOAD=\/usr\/lib\/jvm\/java-17-openjdk\/lib\/server\/libjsig.so java -jar jnitest.jar<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Sending a SIGSEGV to the process (or provoking one from native code), will lead to output like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">Hello<\/span><span class=\"w\"> <\/span><span class=\"n\">World<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Signal<\/span><span class=\"w\"> <\/span><span class=\"mi\">11<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">SIGSEGV<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">\/<\/span><span class=\"n\">home<\/span><span class=\"o\">\/<\/span><span class=\"n\">naums<\/span><span class=\"o\">\/<\/span><span class=\"n\">jni<\/span><span class=\"o\">-<\/span><span class=\"n\">test<\/span><span class=\"o\">\/<\/span><span class=\"n\">build<\/span><span class=\"o\">\/<\/span><span class=\"n\">libJniGlue<\/span><span class=\"o\">.<\/span><span class=\"n\">so<\/span><span class=\"p\">(<\/span><span class=\"n\">SignalHandler<\/span><span class=\"o\">+<\/span><span class=\"mh\">0xb0<\/span><span class=\"p\">)[<\/span><span class=\"mh\">0x7f8034f96289<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><span class=\"o\">\/<\/span><span class=\"n\">libc<\/span><span class=\"o\">.<\/span><span class=\"n\">so<\/span><span class=\"o\">.<\/span><span class=\"mi\">6<\/span><span class=\"p\">(<\/span><span class=\"o\">+<\/span><span class=\"mh\">0x3e710<\/span><span class=\"p\">)[<\/span><span class=\"mh\">0x7f8035188710<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">\/<\/span><span class=\"n\">home<\/span><span class=\"o\">\/<\/span><span class=\"n\">naums<\/span><span class=\"o\">\/<\/span><span class=\"n\">jni<\/span><span class=\"o\">-<\/span><span class=\"n\">test<\/span><span class=\"o\">\/<\/span><span class=\"n\">build<\/span><span class=\"o\">\/<\/span><span class=\"n\">libJniNative<\/span><span class=\"o\">.<\/span><span class=\"n\">so<\/span><span class=\"p\">(<\/span><span class=\"n\">native_hello_world<\/span><span class=\"o\">+<\/span><span class=\"mh\">0x3f<\/span><span class=\"p\">)[<\/span><span class=\"mh\">0x7f8034f8c158<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">\/<\/span><span class=\"n\">home<\/span><span class=\"o\">\/<\/span><span class=\"n\">naums<\/span><span class=\"o\">\/<\/span><span class=\"n\">jni<\/span><span class=\"o\">-<\/span><span class=\"n\">test<\/span><span class=\"o\">\/<\/span><span class=\"n\">build<\/span><span class=\"o\">\/<\/span><span class=\"n\">libJniGlue<\/span><span class=\"o\">.<\/span><span class=\"n\">so<\/span><span class=\"p\">(<\/span><span class=\"n\">Java_de_snaums_jnitest_java_1hello_1world<\/span><span class=\"o\">+<\/span><span class=\"mh\">0x15<\/span><span class=\"p\">)[<\/span><span class=\"mh\">0x7f8034f96394<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">[<\/span><span class=\"mh\">0x7f801c74453a<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">fish<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">Job<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s1\">'java -jar jnitest.jar'<\/span><span class=\"w\"> <\/span><span class=\"n\">terminated<\/span><span class=\"w\"> <\/span><span class=\"n\">by<\/span><span class=\"w\"> <\/span><span class=\"k\">signal<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGABRT<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">Abbruch<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>So now we have a backtrace on stderr. <\/p>\n<h3 id=\"longjumping-back-to-java\">Longjumping back to Java<\/h3>\n<p>Nice, we get a backtrace, this should at least help to identify problems and fix them in the native code, if they arise. But our process is still gone.<\/p>\n<p>Maybe you've found the functions <code>setjmp<\/code> and <code>longjmp<\/code> before, and maybe you've wondered about what they could be used for. These functions perform a \"nonlocal goto\", which is not that useful of a description if you're new to them. <\/p>\n<p>In essence, <code>setjmp<\/code> stores the current processor state, and <code>longjmp<\/code> returns back to it. They will not alter any (global) data, they won't unwind the stack, they will quite literally just <strong>jump<\/strong> back, like a goto. <code>setjmp<\/code> in a sense returns two times: once setting the jump, once returning through <code>longjmp<\/code>. One could use it to implement exceptions and their non-local returns (if you don't need stack-unwinding, that is).<\/p>\n<p>Let's first see, how we use <code>setjmp<\/code> normally, albeit a bit useless:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;iostream&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;setjmp.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">jmp_buf<\/span><span class=\"w\"> <\/span><span class=\"n\">buf<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Starting program\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ first return: rc will be 0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ second return: will be 1 (set by longjmp)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">setjmp<\/span><span class=\"p\">(<\/span><span class=\"n\">buf<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Starting calculation\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ some random maths<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">c<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">d<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">c<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"mi\">12<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">c<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">30<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Value of d:\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">d<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">longjmp<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>g++<span class=\"w\"> <\/span>setjmp.cpp<\/code><\/span>\n<span class=\"code-line\">$<span class=\"w\"> <\/span>.\/a.out<\/span>\n<span class=\"code-line\">Starting<span class=\"w\"> <\/span>program<\/span>\n<span class=\"code-line\">Starting<span class=\"w\"> <\/span>calculation<\/span>\n<span class=\"code-line\">Value<span class=\"w\"> <\/span>of<span class=\"w\"> <\/span>d:32674<\/span>\n<span class=\"code-line\">Starting<span class=\"w\"> <\/span>calculation<\/span>\n<span class=\"code-line\">Value<span class=\"w\"> <\/span>of<span class=\"w\"> <\/span>d:42<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Ah, hang on. What happened here? We've forgot to initialize <code>c<\/code>, so it is unitialized when we first start. The value of <code>d<\/code> is calculated from <code>c<\/code>. Then we set <code>c<\/code> to 30. On our second pass through (returning a second time from <code>setjmp<\/code>), we use the correct value of <code>c<\/code>. So <code>setjmp<\/code> and <code>longjmp<\/code> cannot be used to turn back time, but rather to jump to more or less arbitrary places in your program more or less safely (a lot safer, than if you were to implement a non-local jump yourself in assembly).<\/p>\n<p>Now, we can use it to return control back to our Java program and maybe raise an Exception, so the Java-side could in theory shutdown cleanly. So we extend our glue-library:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"kt\">jmp_buf<\/span><span class=\"w\"> <\/span><span class=\"n\">longjmp_buffer<\/span><span class=\"p\">;<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">SignalHandler<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">signum<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">siginfo_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">si<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">uc<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Signal \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">signum<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\" (SIG\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">sigabbrev_np<\/span><span class=\"p\">(<\/span><span class=\"n\">signum<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\")\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">void<\/span><span class=\"o\">**<\/span><span class=\"w\"> <\/span><span class=\"n\">buffer<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"o\">**<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"n\">malloc<\/span><span class=\"p\">(<\/span><span class=\"mi\">64<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">num<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">backtrace<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">buffer<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">64<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">backtrace_symbols_fd<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">buffer<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">num<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">STDERR_FILENO<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ here we jump back to the glue-function<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">longjmp<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">longjmp_buffer<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ JNI_OnLoad ...<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ we create and throw a NoClassDefFoundError exception<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"nf\">throwException<\/span><span class=\"p\">(<\/span><span class=\"n\">JNIEnv<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">env<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">jclass<\/span><span class=\"w\"> <\/span><span class=\"n\">exClass<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">className<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"java\/lang\/NoClassDefFoundError\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">exClass<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">env<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">FindClass<\/span><span class=\"p\">(<\/span><span class=\"n\">className<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">exClass<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Could not find NoClassDefFoundError, Aborting\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">abort<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">env<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">ThrowNew<\/span><span class=\"p\">(<\/span><span class=\"n\">exClass<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"A JNI Problen occurred\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">Java_de_snaums_jnitest_java_1hello_1world<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">(<\/span><span class=\"n\">JNIEnv<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">env<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jclass<\/span><span class=\"w\"> <\/span><span class=\"n\">cls<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ setting the longjmp. The second time (error case), we'll<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ raise an exception<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">setjmp<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">longjmp_buffer<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">native_hello_world<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">throwException<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">env<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"nf\">Java_de_snaums_jnitest_java_1sum<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">(<\/span><span class=\"n\">JNIEnv<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">env<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jclass<\/span><span class=\"w\"> <\/span><span class=\"n\">cls<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"n\">first<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"n\">second<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ setting the longjmp. The second time (error case), we'll<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ raise an exception<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">setjmp<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">longjmp_buffer<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">jint<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"n\">native_sum<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"p\">)<\/span><span class=\"n\">first<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"p\">)<\/span><span class=\"n\">second<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">throwException<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">env<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>So, the output is, if I introduce a write access to nullpointer in <code>native_hello_world<\/code>:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>java<span class=\"w\"> <\/span>-jar<span class=\"w\"> <\/span>jnitest.jar<\/code><\/span>\n<span class=\"code-line\">Hello<span class=\"w\"> <\/span>World<\/span>\n<span class=\"code-line\">Signal<span class=\"w\"> <\/span><span class=\"m\">11<\/span><span class=\"w\"> <\/span><span class=\"o\">(<\/span>SIGSEGV<span class=\"o\">)<\/span><\/span>\n<span class=\"code-line\">\/home\/naums\/jni-test\/build\/libJniGlue.so<span class=\"o\">(<\/span>SignalHandler+0xb0<span class=\"o\">)[<\/span>0x7fd09b1942d9<span class=\"o\">]<\/span><\/span>\n<span class=\"code-line\">\/usr\/lib\/libc.so.6<span class=\"o\">(<\/span>+0x3e710<span class=\"o\">)[<\/span>0x7fd09b35a710<span class=\"o\">]<\/span><\/span>\n<span class=\"code-line\">\/home\/naums\/jni-test\/build\/libJniNative.so<span class=\"o\">(<\/span>native_hello_world+0x3f<span class=\"o\">)[<\/span>0x7fd09b18a158<span class=\"o\">]<\/span><\/span>\n<span class=\"code-line\">\/home\/naums\/jni-test\/build\/libJniGlue.so<span class=\"o\">(<\/span>Java_de_snaums_jnitest_java_1hello_1world+0x2d<span class=\"o\">)[<\/span>0x7fd09b19448c<span class=\"o\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">[<\/span>0x7fd08474453a<span class=\"o\">]<\/span><\/span>\n<span class=\"code-line\">Exception<span class=\"w\"> <\/span><span class=\"k\">in<\/span><span class=\"w\"> <\/span>thread<span class=\"w\"> <\/span><span class=\"s2\">\"main\"<\/span><span class=\"w\"> <\/span>java.lang.NoClassDefFoundError:<span class=\"w\"> <\/span>A<span class=\"w\"> <\/span>JNI<span class=\"w\"> <\/span>Problen<span class=\"w\"> <\/span>occurred<\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>at<span class=\"w\"> <\/span>de.snaums.jnitest.java_hello_world<span class=\"o\">(<\/span>Native<span class=\"w\"> <\/span>Method<span class=\"o\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>at<span class=\"w\"> <\/span>de.snaums.fun.main<span class=\"o\">(<\/span>fun.java:10<span class=\"o\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We've thrown NoClassDefFoundError as a placeholder, you might want to lookup a list of predefined Exceptions or create a new Exception class yourself to throw. The only thing missing is to catch this Exception, I leave it as a task for the reader.<\/p>\n<h2 id=\"oh-stack-my-stack_1\">Oh Stack, my Stack<\/h2>\n<p>So we've solved the SIGSEGV problem, right? Right?<\/p>\n<p>Yeah, no. We receive a SIGSEGV when we try to write a memory location that does not belong to us, that includes random stray write to anywhere. But, a SIGSEGV would also be raised when your native stack is running out of room. Linux allocates an 8MB stack area (see <code>ulimit<\/code>) for your processes. Your native stack will grow to that size automatically, but can't extend over that limit.<\/p>\n<p>So, when we introduce an infinite recursion (in <code>native_hello_world<\/code>) and fill our native stack, we should see a SIGSEGV and handle it in our handler.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span><span class=\"nv\">LD_PRELOAD<\/span><span class=\"o\">=<\/span>\/usr\/lib\/jvm\/java-17-openjdk\/lib\/server\/libjsig.so<span class=\"w\">  <\/span>java<span class=\"w\"> <\/span>-jar<span class=\"w\"> <\/span>jnitest.jar<\/code><\/span>\n<span class=\"code-line\">...<\/span>\n<span class=\"code-line\">Hello<span class=\"w\"> <\/span>World<\/span>\n<span class=\"code-line\">Hello<span class=\"w\"> <\/span>World<\/span>\n<span class=\"code-line\">Hello<span class=\"w\"> <\/span>World<\/span>\n<span class=\"code-line\">Hello<span class=\"w\"> <\/span>World<\/span>\n<span class=\"code-line\">fish:<span class=\"w\"> <\/span>Job<span class=\"w\"> <\/span><span class=\"m\">1<\/span>,<span class=\"w\"> <\/span><span class=\"s1\">'java -jar jnitest.jar'<\/span><span class=\"w\"> <\/span>terminated<span class=\"w\"> <\/span>by<span class=\"w\"> <\/span>signal<span class=\"w\"> <\/span>SIGSEGV<span class=\"w\"> <\/span><span class=\"o\">(<\/span>Segmentation<span class=\"w\"> <\/span>fault<span class=\"o\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Aha! We get a SIGSEGV, but our native signal handler is not called. Well we've exhausted our stack area, so the libc has no room to place the return address and signal information on the stack and call our signal handler. This causes the process to receive a second SIGSEGV while trying to prepare handling the first one. Now the kernel will hard-abort our application.<\/p>\n<p>Luckily in UNIX there is a function [<a href=\"https:\/\/man.archlinux.org\/man\/sigaltstack.2\">sigaltstack<\/a>], with which we can register an alternative stack for signal handlers to use. Then, when a signal is caught the operating system will switch the signal handler to this alternate stack, place the return information on there, and starting our signal handler.<\/p>\n<p>Let's try that in a normal C++-Test program:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;signal.h&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/mman.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;cstring&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;cstdlib&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;iostream&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ we could also use SIGSTKSZ<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define SIGNAL_STACK_SIZE 4096*4<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">setup_alternate_stack<\/span><span class=\"w\"> <\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int8_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">mem<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int8_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"n\">mmap<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                                    <\/span><span class=\"n\">SIGNAL_STACK_SIZE<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"mi\">2<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">getpagesize<\/span><span class=\"p\">(),<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                                    <\/span><span class=\"n\">PROT_READ<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">PROT_WRITE<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">MAP_PRIVATE<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">MAP_ANON<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                                    <\/span><span class=\"mi\">-1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">mem<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"n\">MAP_FAILED<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"[FATAL] Unable to mmap Signal stack \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ We set up 2 Guard pages, one before our stack, one after<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ so if we write over the end while executing the signal handler<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ we will be killed (safely)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mprotect<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">mem<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">getpagesize<\/span><span class=\"p\">(),<\/span><span class=\"w\"> <\/span><span class=\"n\">PROT_NONE<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mprotect<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">mem<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"n\">getpagesize<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGNAL_STACK_SIZE<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">getpagesize<\/span><span class=\"p\">(),<\/span><span class=\"w\"> <\/span><span class=\"n\">PROT_NONE<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">stack_t<\/span><span class=\"w\"> <\/span><span class=\"n\">ss<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">memset<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">ss<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">stack_t<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">ss<\/span><span class=\"p\">.<\/span><span class=\"n\">ss_flags<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">ss<\/span><span class=\"p\">.<\/span><span class=\"n\">ss_size<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGNAL_STACK_SIZE<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">ss<\/span><span class=\"p\">.<\/span><span class=\"n\">ss_sp<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mem<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"n\">getpagesize<\/span><span class=\"p\">();;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">stack_t<\/span><span class=\"w\"> <\/span><span class=\"n\">os<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">memset<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">os<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">stack_t<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">rc<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">sigaltstack<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">ss<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">os<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"[FATAL] Setting alternate signal stack failed \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"[INFO ] Set alternate signal stack \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Original stack: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">os<\/span><span class=\"p\">.<\/span><span class=\"n\">ss_sp<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\" size \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">os<\/span><span class=\"p\">.<\/span><span class=\"n\">ss_size<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\" flags \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">os<\/span><span class=\"p\">.<\/span><span class=\"n\">ss_flags<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">recurse<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">b<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">a<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">12<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">recurse<\/span><span class=\"p\">(<\/span><span class=\"n\">a<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">SignalHandler<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">signum<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">siginfo_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">si<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">ucontext<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Hello from Stack \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">signum<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">abort<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">setup_alternate_stack<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">sigaction<\/span><span class=\"w\"> <\/span><span class=\"n\">sa<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">memset<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"n\">sa<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ SA_ONSTACK is needed for the handler to run on the alternate stack<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_flags<\/span><span class=\"w\">     <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_SIGINFO<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_RESTART<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_ONSTACK<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_sigaction<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">SignalHandler<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sigemptyset<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_mask<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">sigaction<\/span><span class=\"p\">(<\/span><span class=\"n\">SIGSEGV<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">sa<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"[FATAL] sigaction failed\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">-1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">recurse<\/span><span class=\"p\">(<\/span><span class=\"mi\">12<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Yes, this works.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"p\">[<\/span><span class=\"n\">INFO<\/span><span class=\"w\"> <\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"n\">Set<\/span><span class=\"w\"> <\/span><span class=\"n\">alternate<\/span><span class=\"w\"> <\/span><span class=\"k\">signal<\/span><span class=\"w\"> <\/span><span class=\"n\">stack<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Original<\/span><span class=\"w\"> <\/span><span class=\"n\">stack<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"n\">size<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"n\">flags<\/span><span class=\"w\"> <\/span><span class=\"mi\">2<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">Hello<\/span><span class=\"w\"> <\/span><span class=\"n\">from<\/span><span class=\"w\"> <\/span><span class=\"n\">Stack<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x7f6f59a7e9ac<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">fish<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">Job<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s1\">'.\/a.out'<\/span><span class=\"w\"> <\/span><span class=\"n\">terminated<\/span><span class=\"w\"> <\/span><span class=\"n\">by<\/span><span class=\"w\"> <\/span><span class=\"k\">signal<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGABRT<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">Abbruch<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Now let's try it with Java, adding the alt-stack:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">LD_PRELOAD<\/span><span class=\"o\">=\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><span class=\"o\">\/<\/span><span class=\"n\">jvm<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">-<\/span><span class=\"mi\">17<\/span><span class=\"o\">-<\/span><span class=\"n\">openjdk<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><span class=\"o\">\/<\/span><span class=\"n\">server<\/span><span class=\"o\">\/<\/span><span class=\"n\">libjsig<\/span><span class=\"o\">.<\/span><span class=\"n\">so<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"n\">jar<\/span><span class=\"w\"> <\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.<\/span><span class=\"n\">jar<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"o\">...<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">Hello<\/span><span class=\"w\"> <\/span><span class=\"n\">World<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">Hello<\/span><span class=\"w\"> <\/span><span class=\"n\">World<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">fish<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">Job<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s1\">'LD_PRELOAD=\/usr\/lib\/jvm\/java-17&hellip;'<\/span><span class=\"w\"> <\/span><span class=\"n\">terminated<\/span><span class=\"w\"> <\/span><span class=\"n\">by<\/span><span class=\"w\"> <\/span><span class=\"k\">signal<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGSEGV<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">Adressbereichsfehler<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Hm, funny. It doesn't work.<\/p>\n<p>Let's remind ourselves, Java handles (some) signals itself, like SIGSEGV. Java needs to handle some signals itself, so it registers its own signal handlers with the system. Preloading <code>libjsig.so<\/code> will prevent the native code from registering its native handlers with the system, rather the JVM stores them and will chain them after its own handlers.<\/p>\n<p>This also means, that the Java signal handlers would run on the alternate stack, if this were successful. Unfortunately it isn't. Look at our pure C++ example from above. We've added a flag to our <code>sigaction<\/code> call: <code>SA_ONSTACK<\/code>. This is necessary, so the Signal Handler will be using our alternate stack. If it is missing, the alternate stack is not used for this signal handler. And this missing flag is our problem here. <\/p>\n<p>Unfortunately there is no way for us to overwrite the JVMs signal registrations.<\/p>\n<h3 id=\"going-bonkers\">Going Bonkers<\/h3>\n<p>Or is there?<\/p>\n<p>Remember, <code>libjsig<\/code> intercepts <code>sigaction<\/code>, but it cannot intercept the pure systemcall if we manage to call it ourselves. Funnily enough, the libc presents us a \"nice\" wrapper for it, the <code>syscall<\/code> function. Let's use it to call sigaction on the Java SIGSEGV handler and hard-set the <code>SA_ONSTACK<\/code> flag.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/syscall.h&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;unistd.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ this is stupid, do never do this in real life<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">sigaction<\/span><span class=\"w\"> <\/span><span class=\"n\">java_handler<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">syscall<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">SYS_rt_sigaction<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGSEGV<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">nullptr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">java_handler<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">sigset_t<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">java_handler<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_handler<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"n\">SIG_DFL<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"attempting something very stupid\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">java_handler<\/span><span class=\"p\">.<\/span><span class=\"n\">sa_flags<\/span><span class=\"w\"> <\/span><span class=\"o\">|=<\/span><span class=\"w\"> <\/span><span class=\"n\">SA_ONSTACK<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">syscall<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">SYS_rt_sigaction<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGSEGV<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">java_handler<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">nullptr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">sigset_t<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We call it twice here, first to get the old handler back, so the one that the JVM set, we'll add the <code>SA_ONSTACK<\/code> flag, and set the structure again.<\/p>\n<p>Even if we place this code right before the recursion call, we will have no luck, unfortunately.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"o\">...<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Hello<\/span><span class=\"w\"> <\/span><span class=\"n\">World<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">attempting<\/span><span class=\"w\"> <\/span><span class=\"n\">something<\/span><span class=\"w\"> <\/span><span class=\"n\">very<\/span><span class=\"w\"> <\/span><span class=\"n\">stupid<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">fish<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">Job<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s1\">'LD_PRELOAD=\/usr\/lib\/jvm\/java-17&hellip;'<\/span><span class=\"w\"> <\/span><span class=\"n\">terminated<\/span><span class=\"w\"> <\/span><span class=\"n\">by<\/span><span class=\"w\"> <\/span><span class=\"k\">signal<\/span><span class=\"w\"> <\/span><span class=\"n\">SIGSEGV<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">Adressbereichsfehler<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Somewhere in the JVM it probably resets the handlers or maybe the JVM expects to be on it's normal C stack? I was unable to find out the reason, and more altering of the JVM from the outside would not increase or guarantee coverage. So let's stop here.<\/p>\n<h2 id=\"conclusion_1\">Conclusion<\/h2>\n<p>In this article we've seen that we (sometimes) are able to use signal handlers and signal chaining in native code linked to a Java VM via Java Native Interface (JNI) to handle some errors, report backtraces and maybe even raise exceptions and return to Java. The Java world should then be as short as possible, never allocate more memory, just shut down and maybe restart.<\/p>\n<p>Keep in mind, that most of what we've done in our signal handlers is illegal and may introduce security bugs, leak data or both. So while this is a nice technical excersice, it should never be used in production code. Also there are some native bugs, that cannot be reported by this method, so using a solid mechanism to get coredumps externally should be used, to at least find the bugs that crash the legacy code and eliminate them.<\/p>\n<h2 id=\"image-reference\">Image Reference<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.freepik.com\/free-vector\/black-ecg-heartbeat-line-into-filled-colour-heart_37682078.htm\">Heartbeat Pattern by juice_fish on freepik.com<\/a><\/li>\n<\/ul>\n<h2 id=\"references\">References<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.ibr.cs.tu-bs.de\/users\/dietrich\/advent\/06-sigaction\/\">Advent(2) Der Systemcall Adventskalender<\/a><\/li>\n<li><a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/jni\/spec\/invocation.html\">Java: Invocation API<\/a><\/li>\n<li><a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/17\/troubleshoot\/handle-signals-and-exceptions.html#GUID-F012840D-8E5A-4B6D-8E49-0129A9EE46DB\">Java: Signal Handling<\/a><\/li>\n<li><a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/17\/vm\/signal-chaining.html\">Java: Signal Chaining<\/a><\/li>\n<li><a href=\"https:\/\/man.archlinux.org\/man\/sigaltstack.2\">man sigaltstack<\/a><\/li>\n<li><a href=\"https:\/\/man.archlinux.org\/man\/sigaction.2\">man sigaction(2)<\/a><\/li>\n<li><a href=\"https:\/\/man.archlinux.org\/man\/core\/man-pages\/ld.so.8.en\">man ld.so (LD_PRELOAD)<\/a><\/li>\n<\/ul>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Java"}},{"@attributes":{"term":"Native"}},{"@attributes":{"term":"Interface"}},{"@attributes":{"term":"C++"}},{"@attributes":{"term":"C"}},{"@attributes":{"term":"Linux"}},{"@attributes":{"term":"Library"}},{"@attributes":{"term":"code"}},{"@attributes":{"term":"programming"}},{"@attributes":{"term":"unix"}},{"@attributes":{"term":"signals"}},{"@attributes":{"term":"signal"}},{"@attributes":{"term":"POSIX"}},{"@attributes":{"term":"crash"}},{"@attributes":{"term":"SIGSEGV"}}]},{"title":"JNI Basics: Calling Native Code from Java","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/jni-basics-calling-native-code-from-java.html","rel":"alternate"}},"published":"2023-11-19T23:00:00+01:00","updated":"2023-11-19T23:00:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2023-11-19:\/informatik\/jni-basics-calling-native-code-from-java.html","summary":"<p>Have you ever wondered, how you could call native C\/C++ Code from your Java Code? Say you have a library, that does exactly what you want either because it is legacy code that you want to wrap within Java or you have found an obscure problem, where no Java \u2026<\/p>","content":"<p>Have you ever wondered, how you could call native C\/C++ Code from your Java Code? Say you have a library, that does exactly what you want either because it is legacy code that you want to wrap within Java or you have found an obscure problem, where no Java solution exists. Of course you could rewrite it in Java, which is insanely costly, time consuming and you will get it wrong the first few times. Altenatively you might use the Java Native Interface (JNI) for calling the native code, let's say C++ code, directly.<\/p>\n<p>This article tries to explain how to use JNI in a cook book fashion. We will be using CMake to build our C++ code. We will be working on a Linux System, so the paths and linking behaviour of other systems may be different.<\/p>\n<h2 id=\"before-we-start\">Before we start<\/h2>\n<p>We are going to link a Java program to native C\/C++ code. This is quite a handy way of using old code or maybe run performance critical code natively and have the user interface run in the type safe Java language.<\/p>\n<p>However, this approach also has its shortcomings. If you already know interfaces like COM in Windows then you understand, that COM runs your library in a separate server process. If your COM library crashes it only takes down the server process; your Java (or C# or whatever) client process remains intact, sees an error and can handle it in the safe world appropriately (e.g. by restarting the server and showing an error message). This of course comes with a (heavier) price in performance.<\/p>\n<p>Now, JNI uses the loader\/dynamic linker to load your native libraries into the Java process. While the native function is now present in the same process, there might still be a dozen or so steps between Java and the first of our native functions, so it will incur some run-time overhead over going completely native. Even worse if your native code crashes, which is easier done than said in C\/C++, it will take your whole Java process with it and whatever lives in there. If you run a Tomcat in the same process it will go as well.<\/p>\n<p>Even more nasty, the native code could ruin your whole memory and you might not even catch it. While Java guards the memory quite well from the Java programmers, native code can do nearly whatever it wants. It can read the whole Java heap, the JVM binary code, etc, and it could also write to it, without the operating system intervening, well at least if Write XOR Execute is not activated.<\/p>\n<p>So keep in mind: you must guard native code from user input. Handling malformed or even malicious input in C++ is no easy task. If you don't get it right you might leak memory or crash the whole process. Use the strength of the Java type system to your advantage.<\/p>\n<h2 id=\"prerequisites\">Prerequisites<\/h2>\n<p>We will be using the following tools, so make sure to install them in your distribution:\n* javac\n* cmake\n* gcc<\/p>\n<p>Also make sure, the following libraries are installed on your system. On Arch Linux these are installed into <code>\/usr\/lib\/jvm\/java-17-openjdk\/lib\/server<\/code>. I'm going to use jdk17-openjdk.\n* libjni.so\n* libjvm.so<\/p>\n<p>On Arch Linux it should suffice to install these packages:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>pacman<span class=\"w\"> <\/span>-Syu<span class=\"w\"> <\/span>jdk17-openjdk<span class=\"w\"> <\/span>jdk17-openjre<span class=\"w\"> <\/span>cmake<span class=\"w\"> <\/span>gcc<span class=\"w\"> <\/span>g++<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"starting-with-the-native-code\">Starting with the Native Code<\/h2>\n<p>We'll be starting with our native code. In our example, we'll have two functions, one that just prints <code>Hello World<\/code>, takes no arguments and has no return values. And a second one, that sums two integer-parameters and returns the resulting integer. I'll prefix both with <code>native_<\/code>, which has no significance other than making clear, that this is our native code. So this is our <code>legacy.cpp<\/code>:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ legacy.cpp<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;iostream&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"s\">\"C\"<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">native_hello_world<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Hello World\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">native_sum<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">a<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">b<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">a<\/span><span class=\"o\">+<\/span><span class=\"n\">b<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>For easier reading, I've marked these functions as extern-C. This will deactivate C++ name mangling for these functions. In our example it wouldn't make a difference, because we'll create a separate glue-layer between Java and our native code anyways.<\/p>\n<p>Building this code to a library in CMake looks like this. Place this code in the <code>CMakeLists.txt<\/code> next to your code.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c\"># CMakeLists.txt<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nb\">cmake_minimum_required<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">VERSION<\/span><span class=\"w\"> <\/span><span class=\"s\">3.5<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">project<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">JniTest<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nb\">add_library<\/span><span class=\"p\">(<\/span><span class=\"s\">JniNative<\/span><span class=\"w\"> <\/span><span class=\"s\">SHARED<\/span><span class=\"w\"> <\/span><span class=\"s\">legacy.cpp<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Then configure the project and build it like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>mkdir<span class=\"w\"> <\/span>build<\/code><\/span>\n<span class=\"code-line\">$<span class=\"w\"> <\/span><span class=\"nb\">cd<\/span><span class=\"w\"> <\/span>build<\/span>\n<span class=\"code-line\">$<span class=\"w\"> <\/span>cmake<span class=\"w\"> <\/span>..<\/span>\n<span class=\"code-line\">$<span class=\"w\"> <\/span>make<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Now we have build our native \"legacy\" code, that could have been used in some project from C++. Running <code>nm<\/code> on the resulting <code>libJniNative.so<\/code> reveals these two exported symbols (the capital T indicates a .text-symbol (code), that is exported):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>nm<span class=\"w\"> <\/span>libJniNative.so<\/code><\/span>\n<span class=\"code-line\"><span class=\"m\">0000000000001109<\/span><span class=\"w\"> <\/span>T<span class=\"w\"> <\/span>native_hello_world<\/span>\n<span class=\"code-line\"><span class=\"m\">0000000000001129<\/span><span class=\"w\"> <\/span>T<span class=\"w\"> <\/span>native_sum<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We'll also prepare a header file <code>legacy.h<\/code> to export these function names to other C++ compilation units, so we can use it later:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ legacy.h<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"s\">\"C\"<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">native_hello_world<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">native_sum<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">a<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">b<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"preparing-the-java-code\">Preparing the Java-Code<\/h2>\n<p>Now we'll have to tell Java the names and signatures of our functions and that these functions will be native code. We'll start with the Hello-World function. In a file called <code>jnitest.java<\/code>, we'll create a public class <code>jnitest<\/code>, with a native static function <code>java_hello_world<\/code> and one <code>java_sum<\/code> with two parameters and an int return value. Note <code>int<\/code> and <code>Integer<\/code> are two different types in Java, we want to use the <code>int<\/code>-type here, so we won't need to convert it to C++ ints later on.<\/p>\n<p>But it has a twist. We create a static block in the class, where we tell the Java Virtual Machine to load a library into. We will reference a glue-library, which we'll have to create. This load will fill out the code of both native functions, so calling them later from the Java side will actually land us in our native code.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ jnitest.java<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kn\">package<\/span><span class=\"w\"> <\/span><span class=\"nn\">de.snaums<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">class<\/span> <span class=\"nc\">jnitest<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">static<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">System<\/span><span class=\"p\">.<\/span><span class=\"na\">loadLibrary<\/span><span class=\"p\">(<\/span><span class=\"s\">\"JniGlue\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">static<\/span><span class=\"w\"> <\/span><span class=\"kd\">native<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">java_hello_world<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">static<\/span><span class=\"w\"> <\/span><span class=\"kd\">native<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">java_sum<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">a<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">b<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">static<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">String<\/span><span class=\"o\">[]<\/span><span class=\"w\"> <\/span><span class=\"n\">args<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">jnitest<\/span><span class=\"p\">.<\/span><span class=\"na\">java_hello_world<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">System<\/span><span class=\"p\">.<\/span><span class=\"na\">out<\/span><span class=\"p\">.<\/span><span class=\"na\">println<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Sum: 1+2: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"n\">jnitest<\/span><span class=\"p\">.<\/span><span class=\"na\">java_sum<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"mi\">2<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This code will not run because Java will not understand the link between <code>java_*<\/code> functions and our <code>native_*<\/code> functions. We will have to create glue code for this mapping.<\/p>\n<p>Creating a glue library is a bit more work, but the scenario is, that the legacy code comes directly from some other project and we wouldn't want to alter it for this. So we'll have to introduce a small wrapper around the native code. Afterall we'll have to convert our parameters for the sum-function from Java into C\/C++ types.<\/p>\n<p>Compile this code with the Java Compiler manually to a class-file, to see that this works. Running it won't do, because we have yet to create the glue.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>javac jnitest.java<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"sniffing-some-glue-code\">Sniffing some Glue-Code<\/h2>\n<p>For Java, our functions are actually called <code>de.snaums.jnitest.java_hello_world<\/code>. We've created a package <code>de.snaums<\/code>, in it a class <code>jnitest<\/code> and this class has the Java-end of our native functions in them. However the implementation of these functions is still missing, we'll have to call our native legacy code. Implementing these calls will be done in C++ again in our glue-library.<\/p>\n<p>Using the Java Compiler we generate a header file for the native glue functions, with the <code>-h<\/code> parameter, followed by the output directory and the source file to be analyzed.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>javac<span class=\"w\"> <\/span>-h<span class=\"w\"> <\/span>.<span class=\"w\"> <\/span>jnitest.java<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This will create a <code>de_snaums_jnitest.h<\/code>, with both of our functions declared, but we will need to write the wrapper code ourselves.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ de_snaums_jnitest.h\/glue.h<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/* DO NOT EDIT THIS FILE - it is machine generated *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;jni.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/* Header for class de_snaums_jnitest *\/<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#ifndef _Included_de_snaums_jnitest<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define _Included_de_snaums_jnitest<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#ifdef __cplusplus<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"s\">\"C\"<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#endif<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/*<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * Class:     de_snaums_jnitest<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * Method:    java_hello_world<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * Signature: ()V<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">JNIEXPORT<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">JNICALL<\/span><span class=\"w\"> <\/span><span class=\"n\">Java_de_snaums_jnitest_java_1hello_1world<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"p\">(<\/span><span class=\"n\">JNIEnv<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jclass<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/*<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * Class:     de_snaums_jnitest<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * Method:    java_sum<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * Signature: (II)I<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">JNIEXPORT<\/span><span class=\"w\"> <\/span><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"n\">JNICALL<\/span><span class=\"w\"> <\/span><span class=\"n\">Java_de_snaums_jnitest_java_1sum<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"p\">(<\/span><span class=\"n\">JNIEnv<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jclass<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jint<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jint<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#ifdef __cplusplus<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#endif<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#endif<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Note that the function names are export'ed \"C\" in C++, so the C++ name mangling is deactivated. If it were to interfere with function names, the Java runtime would be unable to link the native java calls to the symbol names in our library, because it has no concept of the C++ name mangling algorithm in each compiler.<\/p>\n<p>Now we need to implement these two functions in a <code>glue.cpp<\/code>. We'll start with our Hello-World function, it takes no parameters and no return values, so we can just call the function straight up. The sum-function will need a bit more work, because we would need to convert the types. However Java-int types are essentially C++ ints, if we aren't going too crazy.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ glue.cpp<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"legacy.h\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;jni.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"s\">\"C\"<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">Java_de_snaums_jnitest_java_1hello_1world<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">(<\/span><span class=\"n\">JNIEnv<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jclass<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">native_hello_world<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"nf\">Java_de_snaums_jnitest_java_1sum<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">(<\/span><span class=\"n\">JNIEnv<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">env<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jclass<\/span><span class=\"w\"> <\/span><span class=\"n\">cls<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"n\">first<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">jint<\/span><span class=\"w\"> <\/span><span class=\"n\">second<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">jint<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"n\">native_sum<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"p\">)<\/span><span class=\"n\">first<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"p\">)<\/span><span class=\"n\">second<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We'll compile this code into a library (<code>libJniGlue<\/code>), in a sense same as before. However, we will need to link it to some Java libraries, which have loads of functionality to convert to and from native\/Java data structures. In this example we've essentially just casted the integer types. When using classes in Java as parameters for native functions, have fun converting them into C\/C++ native types.<\/p>\n<p>Now we have all the pieces together and could start running our Java program, have it load our glue-library, which in turn loads the \"legacy\" native code and we have execution.<\/p>\n<h2 id=\"cmake-compilation\">CMake Compilation<\/h2>\n<p>To make it a bit more elegant, let's use CMake to build everything. We've already had a CMakeLists.txt for building our native code, now include making the Java code into a Java Archive (jar) and also building our glue library:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"err\">\/\/<\/span><span class=\"w\"> <\/span><span class=\"err\">CMakeLists.txt<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nb\">cmake_minimum_required<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">VERSION<\/span><span class=\"w\"> <\/span><span class=\"s\">3.5<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">project<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">JniTest<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nb\">find_package<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">Java<\/span><span class=\"w\"> <\/span><span class=\"s\">REQUIRED<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">find_package<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">JNI<\/span><span class=\"w\"> <\/span><span class=\"s\">REQUIRED<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">include<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">UseJava<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c\"># Example without JNI. Simple HelloWorld class with an entry point.<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">add_jar<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">jnitest<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">         <\/span><span class=\"s\">VERSION<\/span><span class=\"w\"> <\/span><span class=\"s\">0.0.1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">         <\/span><span class=\"s\">ENTRY_POINT<\/span><span class=\"w\"> <\/span><span class=\"s\">de.snaums.jnitest<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">         <\/span><span class=\"s\">SOURCES<\/span><span class=\"w\"> <\/span><span class=\"s\">jnitest.java<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nb\">add_library<\/span><span class=\"p\">(<\/span><span class=\"s\">JniNative<\/span><span class=\"w\"> <\/span><span class=\"s\">SHARED<\/span><span class=\"w\"> <\/span><span class=\"s\">legacy.cpp<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">add_library<\/span><span class=\"p\">(<\/span><span class=\"s\">JniGlue<\/span><span class=\"w\"> <\/span><span class=\"s\">SHARED<\/span><span class=\"w\"> <\/span><span class=\"s\">glue.cpp<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">target_include_directories<\/span><span class=\"p\">(<\/span><span class=\"s\">JniGlue<\/span><span class=\"w\"> <\/span><span class=\"s\">PRIVATE<\/span><span class=\"w\"> <\/span><span class=\"o\">${<\/span><span class=\"nv\">JNI_INCLUDE_DIRS<\/span><span class=\"o\">}<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">target_link_libraries<\/span><span class=\"p\">(<\/span><span class=\"s\">JniGlue<\/span><span class=\"w\"> <\/span><span class=\"s\">PRIVATE<\/span><span class=\"w\"> <\/span><span class=\"o\">${<\/span><span class=\"nv\">JNI_LIBRARIES<\/span><span class=\"o\">}<\/span><span class=\"w\"> <\/span><span class=\"s\">JniNative<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We include the Java-Packages for CMake for the interesting Java-parts: having the Java library and include directories preset. After including Java, we instruct CMake to build a jar <code>jnitest.jar<\/code> from <code>jnitest.java<\/code>, with a given entry point.<\/p>\n<p>Then we add both the native library and the glue library and state the dependencies for the glue library, both the include directory of <code>jni.h<\/code> and the Java libraries. Importantly, we also have to link our glue library to our \"legacy\" code, we want to call into our \"legacy\" code afterall.<\/p>\n<h2 id=\"running-the-jar\">Running the jar<\/h2>\n<p>Now just run the jar, right?<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"o\">$<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"n\">jar<\/span><span class=\"w\"> <\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.<\/span><span class=\"n\">jar<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Exception<\/span><span class=\"w\"> <\/span><span class=\"ow\">in<\/span><span class=\"w\"> <\/span><span class=\"n\">thread<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"main\"<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">UnsatisfiedLinkError<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">no<\/span><span class=\"w\"> <\/span><span class=\"n\">JniGlue<\/span><span class=\"w\"> <\/span><span class=\"ow\">in<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">library<\/span><span class=\"o\">.<\/span><span class=\"n\">path<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"o\">\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">\/<\/span><span class=\"n\">packages<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib64<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib64<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">base<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">ClassLoader<\/span><span class=\"o\">.<\/span><span class=\"n\">loadLibrary<\/span><span class=\"p\">(<\/span><span class=\"n\">ClassLoader<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">2458<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">base<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">Runtime<\/span><span class=\"o\">.<\/span><span class=\"n\">loadLibrary0<\/span><span class=\"p\">(<\/span><span class=\"n\">Runtime<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">916<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">base<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">System<\/span><span class=\"o\">.<\/span><span class=\"n\">loadLibrary<\/span><span class=\"p\">(<\/span><span class=\"n\">System<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">2059<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">de<\/span><span class=\"o\">.<\/span><span class=\"n\">snaums<\/span><span class=\"o\">.<\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.&lt;<\/span><span class=\"n\">clinit<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">5<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Ah, now that's not good. Java loads the jar-file correctly, but then hits a bit of a snag, because it can't find our glue library. Let's look at the directories contents:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>ls<\/code><\/span>\n<span class=\"code-line\">cmake_install.cmake<span class=\"w\">    <\/span>jnitest-0.0.1.jar<span class=\"w\">    <\/span>libJniNative.so<\/span>\n<span class=\"code-line\">CMakeCache.txt<span class=\"w\">         <\/span>jnitest.jar<span class=\"w\">          <\/span>Makefile<\/span>\n<span class=\"code-line\">CMakeFiles<span class=\"w\">             <\/span>libJniGlue.so<span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Ok, so the libraries are clearly there. Well, Linux will only look for libraries in the system paths, and we can see it clearly in the output of Java, because it helpfully lists all the places it looked for our code. We can extend this list, by setting the environment variable <code>LD_LIBRARY_PATH<\/code>.<\/p>\n<p>This environment variable does not only serve Java as a guide where to find libraries, the Linux loader will look in the given places first. It is quite a handy tool, when you explicitly don't want the libraries of the system, e.g. because you linked your program against a different version of a shared object.<\/p>\n<p>Anyway, let's set the environment variable:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\"># fish<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"o\">$<\/span><span class=\"w\"> <\/span><span class=\"n\">set<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"n\">xg<\/span><span class=\"w\"> <\/span><span class=\"n\">LD_LIBRARY_PATH<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">pwd<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\"># bash<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">$<\/span><span class=\"w\"> <\/span><span class=\"k\">export<\/span><span class=\"w\"> <\/span><span class=\"n\">LD_LIBRARY_PATH<\/span><span class=\"w\"> <\/span><span class=\"o\">$<\/span><span class=\"p\">(<\/span><span class=\"n\">pwd<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Then run the jar again to see the output:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>$<span class=\"w\"> <\/span>java<span class=\"w\"> <\/span>-jar<span class=\"w\"> <\/span>jnitest.jar<\/code><\/span>\n<span class=\"code-line\">Sum:<span class=\"w\"> <\/span><span class=\"m\">1<\/span>+2:<span class=\"w\"> <\/span><span class=\"m\">3<\/span><\/span>\n<span class=\"code-line\">Hello<span class=\"w\"> <\/span>World\u23ce<span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"some-fun-to-be-had\">Some fun to be had<\/h2>\n<p>Now, what if we'd want to choose at run-time which library was loaded. Say we have several versions of our legacy code, all in the same directory (because we cannot set <code>LD_LIBRARY_PATH<\/code> in any meaningful way from within Java).<\/p>\n<p>Stunningly this is possible. The static <code>System.loadLibrary<\/code>-block is not executed when the Java program is started, but when the <code>jnitest.class<\/code> is first loaded, i.e. some class or function from it is used. After that, we cannot change what was loaded. But until then, wen can have some fun.<\/p>\n<p>So, if we create a new class <code>jnitestConfig<\/code>, in an own .java file, which only has one member, a String, that sometimes holds the value \"JniGlue\". You see where this is going? From a third .java file - the new entry point - we can then alter the static config class member as long as we haven't called into <code>jnitest<\/code>.<\/p>\n<p>So, lets add <code>jnitestConfig.java<\/code> first:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ jnitestConfig.java<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kn\">package<\/span><span class=\"w\"> <\/span><span class=\"nn\">de.snaums<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">class<\/span> <span class=\"nc\">jnitestConfig<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">static<\/span><span class=\"w\"> <\/span><span class=\"n\">String<\/span><span class=\"w\"> <\/span><span class=\"n\">library<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"JniGlue\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Then add a third .java file, which might present our user-interface. In this case I'll just try and load whatever is in the first parameter of our Java-Program:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ fun.java<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kn\">package<\/span><span class=\"w\"> <\/span><span class=\"nn\">de.snaums<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">class<\/span> <span class=\"nc\">fun<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">public<\/span><span class=\"w\"> <\/span><span class=\"kd\">static<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">String<\/span><span class=\"o\">[]<\/span><span class=\"w\"> <\/span><span class=\"n\">args<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">args<\/span><span class=\"p\">.<\/span><span class=\"na\">length<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">jnitestConfig<\/span><span class=\"p\">.<\/span><span class=\"na\">library<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">args<\/span><span class=\"o\">[<\/span><span class=\"mi\">0<\/span><span class=\"o\">]<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">jnitest<\/span><span class=\"p\">.<\/span><span class=\"na\">java_hello_world<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The <code>System.loadLibrary<\/code> now looks like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ in jnitest.java<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ ..<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">static<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">System<\/span><span class=\"p\">.<\/span><span class=\"na\">loadLibrary<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">jnitestConfig<\/span><span class=\"p\">.<\/span><span class=\"na\">library<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ ...<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Now running the program does exactly what we had before, but we could change the library to be loaded at run-time. If that ever might be useful to you, here you go.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"o\">$<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"n\">jar<\/span><span class=\"w\"> <\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.<\/span><span class=\"n\">jar<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Hello<\/span><span class=\"w\"> <\/span><span class=\"n\">World<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">$<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"n\">jar<\/span><span class=\"w\"> <\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.<\/span><span class=\"n\">jar<\/span><span class=\"w\"> <\/span><span class=\"n\">unhold<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">Exception<\/span><span class=\"w\"> <\/span><span class=\"ow\">in<\/span><span class=\"w\"> <\/span><span class=\"n\">thread<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"main\"<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">UnsatisfiedLinkError<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">no<\/span><span class=\"w\"> <\/span><span class=\"n\">unhold<\/span><span class=\"w\"> <\/span><span class=\"ow\">in<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">library<\/span><span class=\"o\">.<\/span><span class=\"n\">path<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">\/<\/span><span class=\"n\">home<\/span><span class=\"o\">\/<\/span><span class=\"n\">snaums<\/span><span class=\"o\">\/<\/span><span class=\"n\">jni<\/span><span class=\"o\">-<\/span><span class=\"n\">test<\/span><span class=\"o\">\/<\/span><span class=\"n\">build<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">\/<\/span><span class=\"n\">packages<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib64<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib64<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><span class=\"p\">:<\/span><span class=\"o\">\/<\/span><span class=\"n\">usr<\/span><span class=\"o\">\/<\/span><span class=\"n\">lib<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">base<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">ClassLoader<\/span><span class=\"o\">.<\/span><span class=\"n\">loadLibrary<\/span><span class=\"p\">(<\/span><span class=\"n\">ClassLoader<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">2458<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">base<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">Runtime<\/span><span class=\"o\">.<\/span><span class=\"n\">loadLibrary0<\/span><span class=\"p\">(<\/span><span class=\"n\">Runtime<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">916<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">base<\/span><span class=\"o\">\/<\/span><span class=\"n\">java<\/span><span class=\"o\">.<\/span><span class=\"n\">lang<\/span><span class=\"o\">.<\/span><span class=\"n\">System<\/span><span class=\"o\">.<\/span><span class=\"n\">loadLibrary<\/span><span class=\"p\">(<\/span><span class=\"n\">System<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">2059<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">de<\/span><span class=\"o\">.<\/span><span class=\"n\">snaums<\/span><span class=\"o\">.<\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.&lt;<\/span><span class=\"n\">clinit<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"n\">jnitest<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">5<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">at<\/span><span class=\"w\"> <\/span><span class=\"n\">de<\/span><span class=\"o\">.<\/span><span class=\"n\">snaums<\/span><span class=\"o\">.<\/span><span class=\"n\">fun<\/span><span class=\"o\">.<\/span><span class=\"n\">main<\/span><span class=\"p\">(<\/span><span class=\"n\">fun<\/span><span class=\"o\">.<\/span><span class=\"n\">java<\/span><span class=\"p\">:<\/span><span class=\"mi\">10<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Please be aware, this is probably not in the spec of the JVM or JNI, so it might break. You probably shouldn't use this in production code.<\/p>\n<h2 id=\"conclusion-tldr\">Conclusion (tl;dr)<\/h2>\n<p>What have we done? We've created a Java class <code>jnitest<\/code> with 3 methods: one main-function as an entry point to the jar. Two of the methods are marked as native calls.<\/p>\n<p>We've then created a header file with <code>javac -h<\/code> from the Java file and implemented these functions. The implementation is in a separate glue-library; you could also link it directly to your native code, if you know what you are doing and these calls somehow already fulfilled the interfaces.<\/p>\n<p>From this point on, we can use the native functions of our legacy code from anywhere in our Java program. This can be helpful if you can't replace the native code with Java code easily.<\/p>\n<p>While this article only touches on some very basic features, there are great articles and tutorials out there on some more advanced stuff, like allocating Java objects from native code, setting attributes or even throwing Exceptions. A good starting point might be <a href=\"https:\/\/www.baeldung.com\/jni\">Baeldungs Guide to JNI<\/a>.<\/p>\n<h2 id=\"references\">References<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.baeldung.com\/jni\">Baeldungs Guide to JNI<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/mdorier\/java-jni-cmake-example\/blob\/main\/CMakeLists.txt\">Java JNI CMake example (Github)<\/a><\/li>\n<\/ul>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Java"}},{"@attributes":{"term":"Native"}},{"@attributes":{"term":"Interface"}},{"@attributes":{"term":"C++"}},{"@attributes":{"term":"C"}},{"@attributes":{"term":"Linux"}},{"@attributes":{"term":"Library"}},{"@attributes":{"term":"CMake"}},{"@attributes":{"term":"legacy code"}},{"@attributes":{"term":"code"}},{"@attributes":{"term":"programming"}}]},{"title":"Everything Ubus","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/everything-ubus.html","rel":"alternate"}},"published":"2021-12-04T18:45:00+01:00","updated":"2021-12-04T18:45:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2021-12-04:\/informatik\/everything-ubus.html","summary":"<p>Computer scientists seem to reinvent the wheel quite often. For the more cynical observers every new Remote-Procedure-Call implementation looks quite like CORBA or Sun-RPC, but under a different name, different interfaces and - more often than not - some restricted features or inefficiencies. Welcome to Ubus! [<a href=\"https:\/\/git.openwrt.org\/project\/ubus.git\">2<\/a>, <a href=\"https:\/\/openwrt.org\/docs\/techref\/ubus\">4<\/a>]<\/p>\n<h2 id=\"what-is-ubus\">What is Ubus<\/h2>\n<p>Ubus \u2026<\/p>","content":"<p>Computer scientists seem to reinvent the wheel quite often. For the more cynical observers every new Remote-Procedure-Call implementation looks quite like CORBA or Sun-RPC, but under a different name, different interfaces and - more often than not - some restricted features or inefficiencies. Welcome to Ubus! [<a href=\"https:\/\/git.openwrt.org\/project\/ubus.git\">2<\/a>, <a href=\"https:\/\/openwrt.org\/docs\/techref\/ubus\">4<\/a>]<\/p>\n<h2 id=\"what-is-ubus\">What is Ubus<\/h2>\n<p>Ubus is a (local) message bus, specifically for the embedded Linux distribution OpenWRT [<a href=\"https:\/\/openwrt.org\/\">1<\/a>]. OpenWRT is a distribution which brings Linux to many Routers, Access Points or Internet Modems. For example Freifunk mostly uses OpenWRT based installations for their devices.<\/p>\n<p>Ubus contains from a server process (ubusd), which provides the message bus. Client applications can then connect to the Ubus, ask for specific objects on the bus and call methods of these objects, or they can create new objects and provide methods. There are no attributes on objects in the bus, only methods, i.e. remote procedure calls. In a sense, the ubusd-process is more of a broker, handling the discovery of objects.<\/p>\n<p>Ubus is based on libubox [<a href=\"https:\/\/git.openwrt.org\/project\/libubox.git\">3<\/a>], which offers a message-queue like programming interface, allowing C programs to wait for new messages, some functions for marshalling and demarshalling of user data inside so called blobmessages. libubus is <strong>single threaded<\/strong> in design. There is a single <code>blob_buf b<\/code>, so it is only possible to handle one message at a time, adding another thread, which also tries to interact with Ubus will make it crash.<\/p>\n<p>In the remainder of this post I'm gonna refer to the application providing an object and methods as the server, and the one using an object and its methods as the client application.<\/p>\n<h3 id=\"trying-things-out\">Trying things out<\/h3>\n<p>While working on the server is might come in handy to try things out against a - sort of - reference implementation of a client. On OpenWRT there is the <code>ubus<\/code> tool preinstalled. It can be used to query the ubus objects and their methods and to call methods or subscribe to events. These are some examples:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>ubus<span class=\"w\"> <\/span>list<\/code><\/span>\n<span class=\"code-line\">ubus<span class=\"w\"> <\/span>-v<span class=\"w\"> <\/span>list<\/span>\n<span class=\"code-line\">ubus<span class=\"w\"> <\/span>call<span class=\"w\"> <\/span><span class=\"nb\">test<\/span><span class=\"w\"> <\/span>sendHello<span class=\"w\"> <\/span><span class=\"s2\">\"{'id': 12, 'message': 'Testmessage'}\"<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"defining-objects-and-methods-on-the-server_1\">Defining Objects and Methods on the Server<\/h2>\n<p>First, we need to make a type for ubus to use. A type has a name and some methods. Methods are represented by a name which is used to identify the methods on the client-side. Methods also need the callback to be called when the method is requested by a client and it needs a so called polcy, if it takes any parameters. A policy represents the possible arguments of the function and their types. Not, that return values do not need a policy, but you may want one nonetheless, more on that later.<\/p>\n<p>Let's say we want an object \"test\", which has two methods: \"hello\", taking no parameters and returning \"hello world\" and a second one, taking an id of type int and a string \"msg\".<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;libubox\/blobmsg_json.h&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;libubus.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ This enum is helpful, but not necessary.<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ Its entries allow easier access to the methods later on<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">enum<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">HELLO_ID<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">HELLO_MSG<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">__HELLO_MAX<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ the policy describes the paramters of a method<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blobmsg_policy<\/span><span class=\"w\"> <\/span><span class=\"n\">hello_policy<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ id is of type int<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_ID<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"id\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_INT32<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ message is of type string<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_MSG<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"msg\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_STRING<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ forward definitions of our callbacks<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">testHello<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request_data<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">method<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">sendHello<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request_data<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">method<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ setting up a list of methods, one without arguments (hello)<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ and one with the sendHelloPolicy, so (int id, char* msg)<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_method<\/span><span class=\"w\"> <\/span><span class=\"n\">test_methods<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">UBUS_METHOD_NOARG<\/span><span class=\"p\">(<\/span><span class=\"s\">\"hello\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">test_hello<\/span><span class=\"p\">),<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">UBUS_METHOD<\/span><span class=\"p\">(<\/span><span class=\"s\">\"sendHello\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">sendHello<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">sendHelloPolicy<\/span><span class=\"p\">),<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ defining the type \"test\" with the above methods<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object_type<\/span><span class=\"w\"> <\/span><span class=\"n\">test_object_type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">UBUS_OBJECT_TYPE<\/span><span class=\"p\">(<\/span><span class=\"s\">\"test\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">test_methods<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ and defining an object of type test with the methods<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"n\">test_object<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"test\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">test_object_type<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">methods<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">test_methods<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">n_methods<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">ARRAY_SIZE<\/span><span class=\"p\">(<\/span><span class=\"n\">test_methods<\/span><span class=\"p\">),<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We have now the data structures describing an object \"test\" of type \"test\" with the method \"hello\" and \"sendHello\". The list of possible types is this. Note there are arrays and tables which we'll need to cover later a bit more in depth:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">enum<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_type<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_UNSPEC<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_ARRAY<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_TABLE<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_STRING<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_INT64<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_INT32<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_INT16<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_INT8<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_BOOL<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_INT8<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_DOUBLE<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">__BLOBMSG_TYPE_LAST<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_TYPE_LAST<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">__BLOBMSG_TYPE_LAST<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">BLOBMSG_CAST_INT64<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">__BLOBMSG_TYPE_LAST<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Now let's make the ubus daemon aware of our object:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">argc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">**<\/span><span class=\"n\">argv<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ initialize the ubox library<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">uloop_init<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ connect to the ubus socket<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ the parameter may be a path to the ubus socket<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ctx<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">ubus_connect<\/span><span class=\"p\">(<\/span><span class=\"nb\">NULL<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"n\">ctx<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">fprintf<\/span><span class=\"p\">(<\/span><span class=\"n\">stderr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Failed to connect to ubus<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">-1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ubus_add_uloop<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ add our object to the ubus object space<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">ret<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">ubus_add_object<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">test_object<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">ret<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">fprintf<\/span><span class=\"p\">(<\/span><span class=\"n\">stderr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Failed to add object: %s<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">ubus_strerror<\/span><span class=\"p\">(<\/span><span class=\"n\">ret<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ wait in the uloop event queue<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">uloop_run<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ deinit ubus and clean up<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ubus_free<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">uloop_done<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>So now, when we build and run our code, we will see no output of our program, but we will see that there is a new object \"test\" on the ubus and we will see, that it has two methods.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\"># build<\/span><\/code><\/span>\n<span class=\"code-line\">gcc<span class=\"w\"> <\/span>server.c<span class=\"w\"> <\/span>-lubus<span class=\"w\"> <\/span>-lubox<\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\"># run<\/span><\/span>\n<span class=\"code-line\">.\/a.out<\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\"># see<\/span><\/span>\n<span class=\"code-line\">ubus<span class=\"w\"> <\/span>list<\/span>\n<span class=\"code-line\">ubus<span class=\"w\"> <\/span>list<span class=\"w\"> <\/span>-v<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"methods-and-parameters\">Methods and Parameters<\/h3>\n<p>We've seen before the prototype of our callback functions. Let's first have a look into how we demarshal parameters out of the ubus objects:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ - ctx, obj and req are pointers to internal state of the ubus library<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ we could check which object is wanted, but we'll not gonna bother here<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ - method is the name of the method called, useful if there is one<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ callback for more than 1 method<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ - msg is the payload of the request<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">sendHello<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request_data<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">method<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ tb is an array of pointers to blob_attr.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ this serves as indices into the message, from which we'll<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ be able to get our parameters<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">__HELLO_MAX<\/span><span class=\"p\">];<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ parse the message and fill the tb-pointers<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">blobmsg_parse<\/span><span class=\"p\">(<\/span><span class=\"n\">hello_policy<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">ARRAY_SIZE<\/span><span class=\"p\">(<\/span><span class=\"n\">hello_policy<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_data<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_len<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ if there was a message present, print it.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_MSG<\/span><span class=\"p\">])<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"Received %s<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_get_string<\/span><span class=\"p\">(<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_MSG<\/span><span class=\"p\">]));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_ID<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"Recieved ID: %s<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_get_u32<\/span><span class=\"p\">(<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_ID<\/span><span class=\"p\">]));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ Todo: respond<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>For most simpler requests, it is sufficient to call <code>blobmsg_parse<\/code> for demarshalling the message into the <code>tb<\/code> array. Its prototype is:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_parse<\/span><span class=\"p\">(<\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blobmsg_policy<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">policy<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">policy_len<\/span><span class=\"p\">,<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">                  <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">**<\/span><span class=\"n\">tb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">data<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">unsigned<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">len<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><code>blobmsg_parse<\/code> takes the policy and its length, so it knows, which values to expect. The pointer to the array <code>tb<\/code> is used to write indizes into the <code>tb<\/code> array, so we can access the message parameter as <code>tb[1]<\/code> or <code>tb[HELLO_MSG]<\/code>, as the message-entry of the policy is on place 1. The last two parameter is the pointer to the data and its length.<\/p>\n<p>Afterwards we'll have a filled <code>tb<\/code> array. If an entry is <code>NULL<\/code>, the parameter was not found, so the client probably did not send it. Trying to access the parameter will crash our application, so we should always check its existence before using and values and have either sane defaults or ones, that imply that this parameter is missing.<\/p>\n<p>After parsing, we can access our data by using <code>blobmsg_get_...<\/code>. This will return either the value (for scalar values) or a pointer to a string (if it's a string). For string we'd need to copy it, if we'd need it later on, I'm gonna skip that. Not, that there are no <code>blogmsg_get_...<\/code> variants for tables and arrays.<\/p>\n<h4 id=\"arrays-and-tables\">Arrays and Tables<\/h4>\n<p>The fun really starts with arrays and tables. Arrays are in a sense lists of entries, they may even have differing types inside them. I'll assume same typed entries for the time being. Tables are like structs in C. In a way they are arrays with names entries, which is how they can be used in ubus.<\/p>\n<h5 id=\"arrays\">Arrays<\/h5>\n<p><code>blobmsg_parse<\/code> will not get us very far here. Let's assume the following policy of a delete call of a list object:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">enum<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">DELETE_IDS<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">__DELETE_MAX<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blobmsg_policy<\/span><span class=\"w\"> <\/span><span class=\"n\">delete_policy<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">[<\/span><span class=\"n\">DELETE_IDS<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"ids\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_ARRAY<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The delete method takes a single parameter, which has the array-type. However, we don't have to tell ubus at this point which types are inside the array, just that it's an array of things.<\/p>\n<p>Now we can use <code>blobmsg_parse<\/code> to get us the <code>ids<\/code> parameter, but then we'll still have a <code>blob_attr*<\/code> pointer to demarshall. Let's say, we'd want to copy out the array for later use.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">delete_cb<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request_data<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">method<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">__DELETE_MAX<\/span><span class=\"p\">];<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">blobmsg_parse<\/span><span class=\"p\">(<\/span><span class=\"n\">delete_policy<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">__DELETE_MAX<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_data<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_len<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">DELETE_IDS<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ get the length of the array<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">len<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_check_array<\/span><span class=\"p\">(<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">DELETE_IDS<\/span><span class=\"p\">],<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_INT32<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">arr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"n\">malloc<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">len<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"o\">=<\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">cur<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">size_t<\/span><span class=\"w\"> <\/span><span class=\"n\">rem<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ this macro sets up a for loop over all entries in the array<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ cur is always the current object<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ tb[...] is the array to be iterated over<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ and rem is an int for the remainder<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">blobmsg_for_each_attr<\/span><span class=\"p\">(<\/span><span class=\"n\">cur<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">DELETE_IDS<\/span><span class=\"p\">],<\/span><span class=\"w\"> <\/span><span class=\"n\">rem<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">blobmsg_type<\/span><span class=\"p\">(<\/span><span class=\"n\">cur<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_INT32<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"k\">continue<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">arr<\/span><span class=\"p\">[<\/span><span class=\"n\">i<\/span><span class=\"o\">++<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_get_u32<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">cur<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"c1\">\/\/ do stuff<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ respond<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>So we need to get the length of the array. You could iterate over the list two times, once for checking the size and the second one for copying out the values. This is probably what you need to do when the array has differing types in it.<\/p>\n<p>The foreach-macro is a bit on the kernel-level C coding style, which is why I will not copy it in here. You can look it up and try to understand it, I will not.<\/p>\n<h5 id=\"tables\">Tables<\/h5>\n<p>Tables are in a sense the same as arrays, but its values have names. So lets assume, we'd want to add to a key-value store with a typed value (i.e. the parameters are a name, a type-reference and a value).<\/p>\n<p>We would initialize our policy like this, and maybe create a struct for future reference in our key-value store program:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">kv_table<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">key<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">type<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">union<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">value<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">int_val<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">bool<\/span><span class=\"w\"> <\/span><span class=\"n\">bool_val<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ ...<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">enum<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">APPEND_TABLE<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">__APPEND_MAX<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blobmsg_policy<\/span><span class=\"w\"> <\/span><span class=\"n\">append_policy<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">[<\/span><span class=\"n\">APPEND_TABLE<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"table\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_TABLE<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>So then let's take a look into parsing a table. This is a bit boring if the only thing you get passed is a table, but think about nesting table-structures into an array. Then you cannot just add your table names to the policy, but have to iterate over the array and then the table.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">append_cb<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request_data<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">method<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">__APPEND_MAX<\/span><span class=\"p\">];<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">blobmsg_parse<\/span><span class=\"p\">(<\/span><span class=\"n\">append_policy<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">__APPPEND_MAX<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_data<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_len<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">APPEND_TABLE<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">kv_table<\/span><span class=\"w\"> <\/span><span class=\"n\">payload<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">payload<\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">-1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">cur<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">size_t<\/span><span class=\"w\"> <\/span><span class=\"n\">rem<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ as above we'll iterate over the entries of the table<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">blobmsg_for_each_attr<\/span><span class=\"p\">(<\/span><span class=\"n\">cur<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">APPEND_TABLE<\/span><span class=\"p\">],<\/span><span class=\"w\"> <\/span><span class=\"n\">rem<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"kt\">char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_name<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">cur<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">strcmp<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"name\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">key<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"c1\">\/\/ you could (should) check the type of the entry here<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"n\">payload<\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_get_string<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">cur<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">strcmp<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"type\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"n\">payload<\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_get_u32<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">cur<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">strcmp<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"value\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">payload<\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">-1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                    <\/span><span class=\"c1\">\/\/ check blobmsg_type<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                    <\/span><span class=\"c1\">\/\/ ...<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                    <\/span><span class=\"k\">switch<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">payload<\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                        <\/span><span class=\"k\">case<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                            <\/span><span class=\"n\">payload<\/span><span class=\"p\">.<\/span><span class=\"n\">bool_val<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_get_bool<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">cur<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                            <\/span><span class=\"k\">break<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                        <\/span><span class=\"c1\">\/\/ ...<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"c1\">\/\/ do stuff<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ respond<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"sending-responses_2\">Sending Responses<\/h3>\n<p>Other than the parameters, there is no policy needed on what to return. For replying to requests we need the call <code>ubus_send_reply<\/code>:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">ubus_send_reply<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request_data<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>We need to give it the ubus context and the original request and a <code>blob_attr<\/code> message to send. Now let's go back to the \"hello\" method from above, which should just return \"hello world\".<\/p>\n<p>First we need to initialize a <code>struct blob_buf<\/code>. We can have that either static in our C-file or on the stack inside the function. After initialization, we can add values to the buffer, here we just add an attribute \"message\" and send it away with the <code>ubus_send_reply<\/code> call. We give that the <code>head<\/code> pointer to the list of parameters it created.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_buf<\/span><span class=\"w\"> <\/span><span class=\"n\">b<\/span><span class=\"p\">;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">blob_buf_init<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">b<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">blobmsg_add_string<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">b<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"message\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Hello World\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">ubus_send_reply<\/span><span class=\"p\">(<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">buf<\/span><span class=\"p\">.<\/span><span class=\"n\">head<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"nested-responsed-arrays-and-tables\">Nested Responsed: Arrays and Tables<\/h3>\n<p>Sending arrays and tables behaves quite the same, but adds nesting. We will open an attribute of our buffer and add entries to it, either names entries (table) or entries without a name (array). Nesting needs a cookie, which is returned on opening and will be needed for closing, as the nesting operations change the internal state of our buffer-structure and we want to reset it after we're done.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ as a reference: the _array and the _table variants just call<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ _nested with a single bool value changed:<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"nf\">blobmsg_open_nested<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_buf<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">name<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">bool<\/span><span class=\"w\"> <\/span><span class=\"n\">array<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"kr\">inline<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">blobmsg_open_array<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_buf<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">name<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_open_nested<\/span><span class=\"p\">(<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">name<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"kr\">inline<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">blobmsg_open_table<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_buf<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">name<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_open_nested<\/span><span class=\"p\">(<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">name<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">false<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ our code:<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">cookie<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">blobmsg_open_array<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"ids\"<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">blobmsg_add_u32<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">12<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">blobmsg_add_u32<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">13<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">blobmsg_add_u32<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">14<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">blobmsg_close_array<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">buf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">cookie<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>When working with tables, the NULL-parameters are used as names for the fields of the table.<\/p>\n<h2 id=\"client-sending-requests_1\">Client: Sending Requests<\/h2>\n<p>Until now we've only looked at the server code. However sending requests is equally important. The <code>ubus<\/code> tool only gets us so far. First we need to find the object we want to use.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">ubus_lookup_id<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"test\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">id<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"Could not find object test<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><code>ubus_lookup_id<\/code> takes the name of the object we want to have and returns then id of that object. This is an ubus-internal id, we'll be using it to refer to this object, when we call methods of that object.<\/p>\n<p>For calling methods we need either <code>ubus_invoke<\/code> or <code>ubus_invoke_async<\/code>. I will tell you a little secret: the synchronous <code>ubus_invoke<\/code> uses the asynchronous <code>ubus_invoke_async<\/code> internally and (busy) waits for the response. No matter which one we'll use, we will need a complete-callback, which is called, when the response was received. This is the only place, we will be able to see the response-data.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ ubus_data_handler_t, type of the callback<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">ubus_data_handler_t<\/span><span class=\"p\">)(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">type<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ prototype of ubus_invoke<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">ubus_invoke<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">method<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">ubus_data_handler_t<\/span><span class=\"w\"> <\/span><span class=\"n\">cb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">priv<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">timeout<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ usage:<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">ubus_invoke<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">id<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"hello\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">b<\/span><span class=\"p\">.<\/span><span class=\"n\">head<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">myCallback<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">3000<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><code>ubus_invoke<\/code> will return, when the response is received and the transaction complete or the timeout (3000ms) is hit. The return value will indicate whether or not the transaction was successful. In the example call, <code>b<\/code> is again a buffer we filled with values, and NULL is a pointer to private data. This data will be handed right to the complete-callback, so it may be used to hand it memory to write the received response to.<\/p>\n<p>The callback could look like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">enum<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">HELLO_RESP_MSG<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">__HELLO_RESP_MAX<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blobmsg_policy<\/span><span class=\"w\"> <\/span><span class=\"n\">hello_response_policy<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_RESP_MSG<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"message\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">BLOBMSG_TYPE_STRING<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">myCallback<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">type<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">__HELLO_RESP_MAX<\/span><span class=\"p\">];<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ void* priv = req-&gt;priv;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">blobmsg_parse<\/span><span class=\"p\">(<\/span><span class=\"n\">hello_response_policy<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">__HELLO_RESP_MAX<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_data<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">blob_len<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">tb<\/span><span class=\"p\">[<\/span><span class=\"n\">HELLO_RESP_MSG<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"received: %s<\/span><span class=\"se\">\\n<\/span><span class=\"s\">, blobmsg_get_string(tb[HELLO_RESP_MSG]);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Using a policy for return values does make response handling a bit easier. You can of course just handle the parameters yourself. Note, that the private-data pointer is inside of the request-structure.<\/p>\n<p>This is also the point where a code generator would make sense, which generates stubs from a descriptor format, so the boilerplate code is generated, like handling of parameters and return values. This takes some of the flexibility out of it, but makes it easier to use.<\/p>\n<h2 id=\"events-and-subscriptions\">Events and Subscriptions<\/h2>\n<p>Ubus also allows subscribing to objects and sending events. We can subscribe to any object, even ones without a a name (for example when a call returns an object id). As a subscriber, we need a <code>ubus_subscriber<\/code> callback, which contains a callback for every event and a callback for when the object was removed. When subscribing we implicitely create a new object, to which all events are sent.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">ubus_handler_t<\/span><span class=\"p\">)(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_request_data<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">req<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">method<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">ubus_remove_handler_t<\/span><span class=\"p\">)(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_subscriber<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">id<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_subscriber<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"n\">obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ubus_handler_t<\/span><span class=\"w\"> <\/span><span class=\"n\">cb<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ubus_remove_handler_t<\/span><span class=\"w\"> <\/span><span class=\"n\">remove_cb<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">ubus_subscribe<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_subscriber<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">id<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>When we get a remove-callback, we can assume, that the object is gone at will not send any events anymore. Whenever we get an event until then, the <code>cb<\/code>-callback will be called, again allowing us to parse the messages. The sender can notify us under different names (or methods), which can be used to identify certain states or statechanges.<\/p>\n<p>On the sender-side, first we'll add a subscribe-callback, which is called when a subscriber appears or disappears:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">subscriber<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"Subsciber change!<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"n\">test_object<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"test\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">test_object_type<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">methods<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">test_methods<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">n_methods<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">ARRAY_SIZE<\/span><span class=\"p\">(<\/span><span class=\"n\">test_methods<\/span><span class=\"p\">),<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">subscribe_cb<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">subscriber<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>When an event occurs on the server side, we can notify our subscribers by using <code>ubus_notify<\/code>.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">ubus_notify<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_context<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">ctx<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">ubus_object<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">obj<\/span><span class=\"p\">,<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">type<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">blob_attr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">timeout<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Again the <code>msg<\/code> is payload data like above. <code>type<\/code> can be used to identify different state changes and will be passed to the subscriber as a method.<\/p>\n<h2 id=\"timeouts\">Timeouts<\/h2>\n<p>As many of the message loop systems do, uloop also provides timeouts. Give <code>uloop_timeout_add<\/code> a <code>struct uloop_timeout<\/code> and a timeout, it will execute the appropriate callback function when the timeout has expired.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">myTimoutCallback<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">uloop_timeout<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">t<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">uloop_timeout<\/span><span class=\"w\"> <\/span><span class=\"n\">myTimeout<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">cb<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">myTimeoutCallback<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">uloop_timeout_add<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">myTimeout<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">3000<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The callback receives a pointer to the original timeout structure. This is unfortunate, because we cannot add private data to the timeout callback, at least if we don't want to get dirty. If we decide to play dirty, we can use the <code>container_of<\/code> macro, which every Linux Kernel developer knows so well. libubox has <code>contianer_of<\/code> itself in the <code>list.h<\/code>. It is defined as follows:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#ifndef container_of<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define container_of(ptr, type, member) \\<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">    ({  \\<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">        const __typeof__(((type *) NULL)-&gt;member) *__mptr = (ptr);  \\<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">        (type *) ((char *) __mptr - offsetof(type, member));        \\<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">    })<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#endif<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><code>container_of<\/code> takes a pointer, a type and a member of that type. Let's sway we have a structure like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">privateData<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">uloop_timeout<\/span><span class=\"w\"> <\/span><span class=\"n\">t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">private<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>A <code>uloop_timeout<\/code> is embedded into our structure. In this special case, it is (most probably, if the compiler likes us) the first member of the structure, so a normal cast would suffice:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ do not copy!<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">myTimoutCallback<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">uloop_timeout<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">t<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">privateData<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">priv<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">privateData<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"n\">t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>However, if the compiler decides to reorder our structure, we are out of look and just created a bug, which is quite hard to trace. But we can use <code>container_of<\/code>, which will make the compiler do the offset-calculation. We have a pointer to the embedded <code>uloop_timeout<\/code>, and want a pointer to the enclosing structure, which is right around the <code>uloop_timeout<\/code> in memory.<\/p>\n<p>So we tell the compiler the pointer we have, the member inside the enclosing structure, were this pointer points to, and the type of the enclosing structure. Let's alter the structure and see an example:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">privateData2<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">priv2<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">uloop_timeout<\/span><span class=\"w\"> <\/span><span class=\"n\">t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">private<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">myTimoutCallback<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">uloop_timeout<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">timeout<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">privateData<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">priv<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">container_of<\/span><span class=\"p\">(<\/span><span class=\"n\">timeout<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">t<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">privateData2<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Let's see what it does:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>... [ priv2 |       t       | private ] ...<\/code><\/span>\n<span class=\"code-line\">    0       4               x        x+4<\/span>\n<span class=\"code-line\">           \/ \\<\/span>\n<span class=\"code-line\">            |<\/span>\n<span class=\"code-line\">         timeout<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><code>container_of<\/code> calculates the offset of <code>timeout<\/code> inside our enclosing structure. We tell it the member to which <code>timeout<\/code> points, which is t, then calculates the offset of that member inside the struct and substracts that from our original pointer. The problem here is, that we cannot be totally sure, that this structure is <em>always<\/em> around the timeout. So when using <code>container_of<\/code> make sure and be absolutely certain, that you <em>always<\/em> have the embedding structure around the embedded structure. The compiler won't warn you.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Ubus is a (more or less) simple message bus for embedded Linux distributions (like OpenWRT). You can call methods, subscribe and send events and add timeouts. Unfortunately ubus is not designed for multithreaded applications, throwing segementation faults left, right and center when a second thread comes anywhere near ubus-code.<\/p>\n<p>As always with these message-loops you need to call <code>uloop_run<\/code> repeatedly (or once to that matter), if you want to get new events or messages. If your C-code takes a while, you will not get new messages - of course you don't, you only have one single thread.<\/p>\n<p>A big drawback is, that ubus is essentially written like the Linux Kernel, which sometimes makes it hard to read. Also there is next to no documentation for any of it, apart from the code (at least that I can find). Going through the examples only brings you that far, reading through the tests of libubox gives a bit more insight, but still there is no place, which really explains these things. Unfortunately there is also no (publically available) code generator of stub-code.<\/p>\n<p>But now there is at least some documentation. If you find any problems or mistakes, please let me know!<\/p>\n<h2 id=\"references\">References<\/h2>\n<p>[1] <a href=\"https:\/\/openwrt.org\/\">https:\/\/openwrt.org\/<\/a>\n[2] <a href=\"https:\/\/git.openwrt.org\/project\/ubus.git\">https:\/\/git.openwrt.org\/project\/ubus.git<\/a>\n[3] <a href=\"https:\/\/git.openwrt.org\/project\/libubox.git\">https:\/\/git.openwrt.org\/project\/libubox.git<\/a>\n[4] <a href=\"https:\/\/openwrt.org\/docs\/techref\/ubus\">https:\/\/openwrt.org\/docs\/techref\/ubus<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"OpenWRT"}},{"@attributes":{"term":"Linux"}},{"@attributes":{"term":"Ubus"}},{"@attributes":{"term":"Bus"}},{"@attributes":{"term":"Message Bus"}},{"@attributes":{"term":"C"}},{"@attributes":{"term":"Programming"}},{"@attributes":{"term":"Coding"}},{"@attributes":{"term":"Embedded"}}]},{"title":"Samsung NX300: Dissecting a Hacked Firmware","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/fotografie\/samsung-nx300-disecting-a-hacked-firmware.html","rel":"alternate"}},"published":"2021-06-13T00:30:00+02:00","updated":"2021-06-13T00:30:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2021-06-13:\/fotografie\/samsung-nx300-disecting-a-hacked-firmware.html","summary":"<p>I mentioned in an earlier blog post, that I'm working on the Samsung NX300(m) mirrorless cameras and trying to get some features to work. I outlined in that post a way to get unlimited movie record length. While this method seems to screw up the time remaining, recording always \u2026<\/p>","content":"<p>I mentioned in an earlier blog post, that I'm working on the Samsung NX300(m) mirrorless cameras and trying to get some features to work. I outlined in that post a way to get unlimited movie record length. While this method seems to screw up the time remaining, recording always stops just over the 4GB file size marker on my NX300m cameras.<\/p>\n<p>Furtunately someone made a hacked formware [<a href=\"https:\/\/www.dpreview.com\/forums\/post\/56754944\">1<\/a>] for the NX300 cameras, which allows unlimted movie record times, and it seems to work fine at least on my NX300. The link [<a href=\"https:\/\/mega.nz\/file\/RAJCiIIZ#LappfCn1QSppxx9eu49DvTqS9GhvSYA_Edqr6S6o2ZA\">2<\/a>] leads you to the download for this specific firmware.<\/p>\n<p>In this blog post I'll dive into the differences of the hacked version and an official image of the latest version 1.45 of the firmware for the NX300 camera. This is gonna get technical, so grab your ARM Instruction Set Manual and join me on that journey.<\/p>\n<h2 id=\"a-tale-of-two-binary-images\">A Tale of two Binary Images<\/h2>\n<p>It is hinted in the forum posts, that the firmware for the NX300 and the NX300M are packed differently.  I already know, that Samsung shipped different software for the M-models, so I expect I cannot just copy over the hacked NX300 binary to the NX300M. However finding the differences between the original firmware and the one with unlimited video record length may give me a lead to what might be necessary for the same effect on the NX300M.<\/p>\n<p>From the OpenSource-parts of the firmware of the NX300M I already know, that the binary I should be most interested in is the <code>di-camera-app-nx300m<\/code> or similar, which is the brains of the operation, managing the software modes and configuring the drimeIV ASIC to capture a photo, i.e. read-out the sensor and create an JPEG of that readout on the SD-Card, or capture a movie with sound and encode it as H.264 in mp4-files.<\/p>\n<h3 id=\"unpackung-and-mounting-the-firmware-images\">Unpackung and Mounting the Firmware Images<\/h3>\n<p>First I need to unpack the <code>nx300.bin<\/code> firmware images and mount the linux root-filesystem of the camera in my system. I'm using an Arch Linux, so if you want to do the same (or similar thing) on a different distribution, your packages may be called differently.<\/p>\n<p>To unpack the firmware images, I wrote myself a C-program (see below), <code>mmap<\/code>ing the header [<a href=\"https:\/\/sites.google.com\/site\/nxcryptophotography\/diy-firmware\">3<\/a>] of the firmware, finding the right offsets and using <code>dd<\/code> to extract the different parts. See, the firmware image is essentially a header and then <code>cat<\/code>ed files behind each other. The header contains the offset and size of each section in the firmware image.<\/p>\n<p>The only file I'm actually interested in, is the <code>platform.img<\/code>, which contains the whole linux filesystem. The others are some kind of loaders and probably firmware for the drime4 itself. However it is not simply a copy of an ext4-filesystem to be mounted, it is a UBIFS, which is used for flash based filesystems.<\/p>\n<p>Mounting the filesystem is a bit cumbersome, so I've written myself a Makefile. First the <code>nandsim<\/code> module is loaded, the platform.img is copied into the mtd0 device of the nandsim module, then <code>ubi<\/code> is loaded and mtd0 is attached to the ubi-driver. Lastly the ubi-device is mounted to <code>\/mnt\/ubi<\/code>, which allows us finally to view the goods inside.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"nf\">mount<\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">platform<\/span>.<span class=\"n\">img<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"run as root\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>modprobe<span class=\"w\"> <\/span>nandsim<span class=\"w\"> <\/span><span class=\"nv\">cache_file<\/span><span class=\"o\">=<\/span>.\/temp_nand.dat<span class=\"w\"> <\/span><span class=\"nv\">first_id_byte<\/span><span class=\"o\">=<\/span>0x20<span class=\"w\"> <\/span><span class=\"nv\">second_id_byte<\/span><span class=\"o\">=<\/span>0xac<span class=\"w\"> <\/span><span class=\"nv\">third_id_byte<\/span><span class=\"o\">=<\/span>0x00<span class=\"w\"> <\/span><span class=\"nv\">fourth_id_byte<\/span><span class=\"o\">=<\/span>0x15<\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>dd<span class=\"w\"> <\/span><span class=\"k\">if<\/span><span class=\"o\">=<\/span>platform.img<span class=\"w\"> <\/span><span class=\"nv\">of<\/span><span class=\"o\">=<\/span>\/dev\/mtd0<span class=\"w\"> <\/span><span class=\"nv\">bs<\/span><span class=\"o\">=<\/span><span class=\"m\">2048<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>modprobe<span class=\"w\"> <\/span>ubi<\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>ubiattach<span class=\"w\"> <\/span>-m<span class=\"w\"> <\/span><span class=\"m\">0<\/span><span class=\"w\"> <\/span>-O<span class=\"w\"> <\/span><span class=\"m\">2048<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>-mkdir<span class=\"w\"> <\/span>\/mnt\/ubi<\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>mount<span class=\"w\"> <\/span>-t<span class=\"w\"> <\/span>ubifs<span class=\"w\"> <\/span>ubi0_0<span class=\"w\"> <\/span>\/mnt\/ubi<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>You may need the package <code>mtd-utils<\/code> for mounting the image.<\/p>\n<h3 id=\"finding-differences\">Finding Differences<\/h3>\n<p>Now the real problem starts. How to find differences in the image? I already know from the opensource package, that there are loads of libraries and the <code>di-camera-app<\/code>, which implement most of the cameras functionality. Then maybe there might be some files not present in one or the other.<\/p>\n<p>So i've written myself a small, overengineered bash script md5ing all files and comparing the hashes against each other. The differences show in <code>\/etc\/version.info<\/code> with an additional byte, that looks astonishingly like a 'c' after the version number, and in the <code>di-camera-app<\/code>. The other differing files are due to a bug I didn't bother to fix, as the script does not handle spaces in the file paths well at all.<\/p>\n<h3 id=\"dissecting-the-disassembly\">Dissecting the Disassembly<\/h3>\n<p>Ok, we've essentially found out, that the main difference seems to be in the <code>di-camera-app<\/code>, which is more or less expected, since this binary handles all of the ARM-side software of the camera. So, I've run <code>arm-none-eabi-objdump<\/code> on them and took a <code>diff<\/code> (for the lulz I repeated that with forced thumb-mode, which did not go well, so I can be sure, that this code seems to be regular ARM code).<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"gu\">2c2<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"gd\">&lt; di-camera-app-hacked:     file format elf32-littlearm<\/span><\/span>\n<span class=\"code-line\"><span class=\"gs\">---<\/span><\/span>\n<span class=\"code-line\"><span class=\"gi\">&gt; di-camera-app-original:     file format elf32-littlearm<\/span><\/span>\n<span class=\"code-line\">381052c381052<\/span>\n<span class=\"code-line\"><span class=\"gd\">&lt;   177670: e3e03102    mvn r3, #-2147483648    ; 0x80000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"gs\">---<\/span><\/span>\n<span class=\"code-line\"><span class=\"gi\">&gt;   177670: e3a03000    mov r3, #0<\/span><\/span>\n<span class=\"code-line\">443109c443109<\/span>\n<span class=\"code-line\"><span class=\"gd\">&lt;   1b3840: e3e03102    mvn r3, #-2147483648    ; 0x80000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"gs\">---<\/span><\/span>\n<span class=\"code-line\"><span class=\"gi\">&gt;   1b3840: e3003706    movw    r3, #1798   ; 0x706<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Aha! Two differences, about 4 changed bytes, that makes all the difference. But why? Well, let's look at the disassembly of the unofficial firmware, especially around where I found the differences:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"err\">00177660<\/span><span class=\"w\"> <\/span><span class=\"err\">&lt;<\/span><span class=\"nf\">_Z28UI_Get_Storage_File_Max_Sizev@@Base<\/span><span class=\"err\">&gt;<\/span><span class=\"p\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177660:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e52db004<\/span><span class=\"w\">    <\/span><span class=\"no\">push<\/span><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"no\">fp<\/span><span class=\"p\">}<\/span><span class=\"w\">        <\/span><span class=\"c1\">; (str fp, [sp, #-4]!)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177664:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e28db000<\/span><span class=\"w\">    <\/span><span class=\"no\">add<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177668:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24dd00c<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#12<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">17766<\/span><span class=\"nl\">c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3e02000<\/span><span class=\"w\">    <\/span><span class=\"no\">mvn<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"err\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"err\">177670:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3e03102<\/span><span class=\"w\">    <\/span><span class=\"no\">mvn<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-2147483648<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x80000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177674:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b20fc<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-12<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177678:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b20dc<\/span><span class=\"w\">    <\/span><span class=\"no\">ldrd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-12<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">17767<\/span><span class=\"nl\">c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00002<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177680:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01003<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177684:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e28bd000<\/span><span class=\"w\">    <\/span><span class=\"no\">add<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">177688:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e8bd0800<\/span><span class=\"w\">    <\/span><span class=\"no\">ldmfd<\/span><span class=\"w\">   <\/span><span class=\"no\">sp<\/span><span class=\"p\">!,<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"no\">fp<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">17768<\/span><span class=\"nl\">c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e12fff1e<\/span><span class=\"w\">    <\/span><span class=\"no\">bx<\/span><span class=\"w\">  <\/span><span class=\"no\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>I've marked the changed line. At first there was an <code>mov r3, #0<\/code> which would have set the register <code>r3<\/code> to the value of 0, now it's a move negative <code>mvn r3, #0x80000000<\/code>. This instruction bitwise negates the source operand and sets the destination with the value, i.e. making r3 the largest possible signed 32 bit value <code>0x7fffffff<\/code>. <\/p>\n<p>From what I can get, this seems to be intializing one of the two return parameters to the maximal value, so make the calling code think, that the maximal file size of the file system is essentially unlimited. However, the code looks somewhat weird. <code>strd<\/code> and <code>ldrd<\/code> are store and load-operations on double-words, so I assume that this code means <code>r2<\/code> and <code>r3<\/code> are stored onto the newly created stack and read back from it. It looks to me, that the Samsung engineers forgot to enable compiler optimizations, as no normal not-braindead-compiler wouldn't keep these values just in the registers.<\/p>\n<p>A bit concerning is the <code>bx<\/code> instruction at the end, which is a branch (to the Link Register <code>lr<\/code>, which is the ARM version of a return), but with changing the instruction set. So whatever it returns to should be Thumb code, if I understand that correctly. Maybe I'll have to do more research on that.<\/p>\n<p>Well, let's get to the second change. I'll abbreviate it here, but I'll put the whole file in the appendix.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"err\">001<\/span><span class=\"nf\">b3584<\/span><span class=\"w\"> <\/span><span class=\"err\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"err\">&gt;<\/span><span class=\"p\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"na\">...<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3610:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebff0fff<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">177614<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Storage_Free_Spacev@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3614:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a02000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3618:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b361c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b26fc<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-108<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff94<\/span><\/span>\n<span class=\"code-line\"><span class=\"err\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3620:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebff100e<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">177660<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z28UI_Get_Storage_File_Max_Sizev@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3624:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a02000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3628:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b362c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b27f4<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-116<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff8c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3630:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a02000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3634:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3638:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b22f4<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-36<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffdc<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b363c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3640:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3028<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-40<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3644:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a00053<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#83<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x53<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3648:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed3f2<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168618<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b364c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3650:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3654:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a00050<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#80<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x50<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3658:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed3ee<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168618<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b365c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3660:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b307c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3664:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b007c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3668:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a01000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b366c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">eb001748<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">1b9394<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z22UI_Set_Attr_Movie_Size18eUI_CAP_MOVIE_SIZE@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x1100<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3670:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3674:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3060<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-96<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3678:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b007c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b367c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebffff3c<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">1b3374<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z21UI_Get_Video_Bit_Rate18eUI_CAP_MOVIE_SIZE@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3680:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3684:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3058<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-88<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3688:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24b2084<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#132<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b368c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24b3088<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#136<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3690:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00002<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3694:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01003<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3698:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebffff98<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">1b3500<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z21UI_Get_Audio_Bit_RatePiS_@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b369c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2068<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-104<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff98<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36a0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3070<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-112<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff90<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36a4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">...<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37e8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfadace<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">6a328<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">mm_util_movie_record_time@plt<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37ec:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37f0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37f4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37f8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37fc:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000006<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b381c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x298<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3800:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3804:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e2832003<\/span><span class=\"w\">    <\/span><span class=\"no\">add<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3808:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b380c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">b1a03002<\/span><span class=\"w\">    <\/span><span class=\"no\">movlt<\/span><span class=\"w\">   <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3810:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03143<\/span><span class=\"w\">    <\/span><span class=\"no\">asr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3814:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3818:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000007<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b383c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2b8<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b381c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3820:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530001<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3824:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000004<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b383c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2b8<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3828:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b382c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a02fa3<\/span><span class=\"w\">    <\/span><span class=\"no\">lsr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#31<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3830:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e0823003<\/span><span class=\"w\">    <\/span><span class=\"no\">add<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3834:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a030c3<\/span><span class=\"w\">    <\/span><span class=\"no\">asr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3838:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b383c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"err\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3840:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3e03102<\/span><span class=\"w\">    <\/span><span class=\"no\">mvn<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-2147483648<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x80000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3844:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3848:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3858<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2d4<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b384c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3003707<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1799<\/span><span class=\"w\">   <\/span><span class=\"c1\">; 0x707<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3850:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3854:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000001<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3860<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2dc<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3858:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b385c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3860:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b307c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3864:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530007<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#7<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">...<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This one is a bit bigger. First, we find the only call-site of the StorageMax function we saw our first change in. The return values are stored in <code>r2<\/code> and <code>r3<\/code> and placed on the stack. I'd assume, that there is a <code>cmp<\/code> (compare) statement with these values later on, which would stop the recording, when the file size limit is hit.<\/p>\n<p>Then later on, near the middle of the function, but at the end of the excerpt, we find our second change. Normally we'd write the value of 1798 into register <code>r3<\/code>, but we want to write signed integer max. You know 1798 looks an awful lot like the maximal amount of seconds a video can be. And sure enough, when we divide 60 from it, we get 29.9 minutes, which is the maximal time for 1080p30 videos. In the 1080p60 video mode, the time is reduced to 21 minutes and a few seconds, because the file size exceeds the 4G limit by the FAT-filesystem. However the SD cards are formatted to exfat in the NX300M which allows for nearly unlimited file sized.<\/p>\n<p>One thing to note here is, that there is a function UI::GetVideoBitRate in the function. One can savely assume, that this function may be used for communication with the drime4 ASIC to set the correct bitrate and quality setting for the movie recording. That may of course also be a red hering.<\/p>\n<h2 id=\"conclusion_1\">Conclusion<\/h2>\n<p>So, from what I can understand, the breaking points on the NX300 were the maximal file size of the filesystem. I did not see where the function would get the information about the file system on the SD card, so this may or may not be breakable by using an ext2-formatted card and a cross compiled ext2-kernel module [<a href=\"https:\/\/lemmster.de\/cross-compile-kernel-module-samsung-nx300-ubnut-14.04.html\">4<\/a>]. <\/p>\n<p>The second change was to eliminate the hard limit to 30 minutes of movie recording. I haven't investigated that close enough, but maybe there is a check for the system parameter, where we could disable the recording limit.<\/p>\n<h2 id=\"references\">References<\/h2>\n<p>[1] <a href=\"https:\/\/www.dpreview.com\/forums\/post\/56754944\">https:\/\/www.dpreview.com\/forums\/post\/56754944<\/a><br\/>\n[2] <a href=\"https:\/\/mega.nz\/file\/RAJCiIIZ#LappfCn1QSppxx9eu49DvTqS9GhvSYA_Edqr6S6o2ZA\">https:\/\/mega.nz\/file\/RAJCiIIZ#LappfCn1QSppxx9eu49DvTqS9GhvSYA_Edqr6S6o2ZA<\/a><br\/>\n[3] <a href=\"https:\/\/sites.google.com\/site\/nxcryptophotography\/diy-firmware\">https:\/\/sites.google.com\/site\/nxcryptophotography\/diy-firmware<\/a><br\/>\n[4] <a href=\"https:\/\/lemmster.de\/cross-compile-kernel-module-samsung-nx300-ubnut-14.04.html\">https:\/\/lemmster.de\/cross-compile-kernel-module-samsung-nx300-ubnut-14.04.html<\/a><br\/><\/p>\n<h2 id=\"appendix\">Appendix<\/h2>\n<h3 id=\"extractorc\">extractor.c<\/h3>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ CC-BY-NC-SA Stefan Naumann<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/types.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/stat.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/mman.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;sys\/wait.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;fcntl.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;errno.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;unistd.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;assert.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdlib.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdio.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdint.h&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdbool.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;string.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">size<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">crc<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">start<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">unknown<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/ maybe address for flash?<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PRINT_META(name,x) printf(\"%s { \\n\\tsize : 0x%08lx\\n\\tcrc  : 0x%08lx\\n\\tstart: 0x%08lx\\n\\tunknown: %lx\\n};\\n\", name, x.size, x.crc, x.start, x.unknown);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">header<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint8_t<\/span><span class=\"w\"> <\/span><span class=\"n\">stuff<\/span><span class=\"p\">[<\/span><span class=\"mh\">0x40<\/span><span class=\"p\">];<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"w\"> <\/span><span class=\"n\">vimage<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"w\"> <\/span><span class=\"n\">d4ipl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"w\"> <\/span><span class=\"n\">d4pnlbl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"w\"> <\/span><span class=\"n\">uimage<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"w\"> <\/span><span class=\"n\">platform<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"w\"> <\/span><span class=\"n\">pcache<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">name<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"vImage\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"D4_IPL\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"D4_PNLBL\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"uImage\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"platform\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"pcache\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">fname<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"vImage\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"D4_IPL.bin\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"D4_PNLBL.bin\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"uImage\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"platform.img\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s\">\"pcache.list\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static_assert<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">4<\/span><span class=\"o\">*<\/span><span class=\"mi\">4<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">static_assert<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">sizeof<\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">header<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xa0<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">bool<\/span><span class=\"w\"> <\/span><span class=\"nf\">checkCRC<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">filename<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">crc<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ why bother?<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">ddout<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">m<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">inname<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">filename<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">assert<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">strlen<\/span><span class=\"p\">(<\/span><span class=\"n\">filename<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">17<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">assert<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">strlen<\/span><span class=\"p\">(<\/span><span class=\"n\">inname<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">197<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">pid<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">fork<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"n\">skip<\/span><span class=\"p\">[<\/span><span class=\"mi\">20<\/span><span class=\"p\">]<\/span><span class=\"o\">=<\/span><span class=\"p\">{<\/span><span class=\"mi\">0<\/span><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"n\">count<\/span><span class=\"p\">[<\/span><span class=\"mi\">20<\/span><span class=\"p\">]<\/span><span class=\"o\">=<\/span><span class=\"p\">{<\/span><span class=\"mi\">0<\/span><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"n\">iff<\/span><span class=\"p\">[<\/span><span class=\"mi\">200<\/span><span class=\"p\">]<\/span><span class=\"o\">=<\/span><span class=\"p\">{<\/span><span class=\"mi\">0<\/span><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"n\">off<\/span><span class=\"p\">[<\/span><span class=\"mi\">20<\/span><span class=\"p\">]<\/span><span class=\"o\">=<\/span><span class=\"p\">{<\/span><span class=\"mi\">0<\/span><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"n\">bs<\/span><span class=\"p\">[<\/span><span class=\"mi\">20<\/span><span class=\"p\">]<\/span><span class=\"o\">=<\/span><span class=\"s\">\"bs=1\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">pid<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">errno<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"o\">?<\/span><span class=\"w\"> <\/span><span class=\"n\">errno<\/span><span class=\"w\"> <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"n\">EINVAL<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">pid<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">bsi<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">while<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">m<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">size<\/span><span class=\"w\"> <\/span><span class=\"o\">%<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">bsi<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;&amp;<\/span><span class=\"w\"> <\/span><span class=\"n\">bsi<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">bsi<\/span><span class=\"o\">++<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">bsi<\/span><span class=\"o\">--<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">bsi<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;=<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">bsi<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">snprintf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">skip<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">20<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"skip=%ld\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">m<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">start<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">snprintf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">count<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">20<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"count=%ld\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">m<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">size<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">snprintf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">iff<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">200<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"if=%s\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">inname<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">snprintf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">off<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">20<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"of=%s\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">filename<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">snprintf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">bs<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">20<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"bs=%d\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"%s %s %s %s %s %s status=progress<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"dd\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">skip<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">count<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">iff<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">off<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">bs<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">execlp<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"dd\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"dd\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">skip<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">count<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">iff<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">off<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">bs<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"status=progress\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">exit<\/span><span class=\"p\">(<\/span><span class=\"n\">EINVAL<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">rc<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">waitpid<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">pid<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">rc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">WEXITSTATUS<\/span><span class=\"p\">(<\/span><span class=\"n\">rc<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">argc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"o\">**<\/span><span class=\"w\"> <\/span><span class=\"n\">argv<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">argc<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"mi\">2<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"usage: %s {filename}<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">argv<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">EINVAL<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">errno<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">fd<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">open<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">argv<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span><span class=\"w\"> <\/span><span class=\"n\">O_RDONLY<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">fd<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"open: %s<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">strerror<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">errno<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">errno<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">header<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">hdr<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">header<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"n\">mmap<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xa0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">PROT_READ<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">MAP_PRIVATE<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">fd<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">close<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">fd<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"n\">hdr<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"n\">MAP_FAILED<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"mmap: %s<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">strerror<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">errno<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">errno<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">meta<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">m<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">hdr<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">vimage<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"o\">&lt;<\/span><span class=\"mi\">6<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><span class=\"o\">++<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">PRINT_META<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">name<\/span><span class=\"p\">[<\/span><span class=\"n\">i<\/span><span class=\"p\">],<\/span><span class=\"w\"> <\/span><span class=\"n\">m<\/span><span class=\"p\">[<\/span><span class=\"n\">i<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">ddout<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">m<\/span><span class=\"p\">[<\/span><span class=\"n\">i<\/span><span class=\"p\">],<\/span><span class=\"w\"> <\/span><span class=\"n\">argv<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span><span class=\"w\"> <\/span><span class=\"n\">fname<\/span><span class=\"p\">[<\/span><span class=\"n\">i<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">munmap<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">hdr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xa0<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"diffsh\">diff.sh<\/h3>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"ch\">#!\/bin\/bash<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"c1\"># CC-BY-SA-NC by Stefan Naumann<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nv\">NORMAL<\/span><span class=\"o\">=<\/span><span class=\"m\">32<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">WARN<\/span><span class=\"o\">=<\/span><span class=\"m\">31<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">CHECK<\/span><span class=\"o\">=<\/span><span class=\"m\">34<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">## \"simple\" logging function using asci escape colors and output files<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">function<\/span><span class=\"w\"> <\/span>log<span class=\"w\"> <\/span><span class=\"o\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">level<\/span><span class=\"o\">=<\/span><span class=\"si\">${<\/span><span class=\"nv\">2<\/span><span class=\"k\">:-<\/span><span class=\"si\">${<\/span><span class=\"nv\">NORMAL<\/span><span class=\"si\">}}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">output<\/span><span class=\"o\">=<\/span><span class=\"si\">${<\/span><span class=\"nv\">3<\/span><span class=\"k\">:-<\/span><span class=\"s2\">\"\/dev\/stdout\"<\/span><span class=\"si\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span>-e<span class=\"w\"> <\/span><span class=\"s2\">\"\\033[<\/span><span class=\"si\">${<\/span><span class=\"nv\">level<\/span><span class=\"si\">}<\/span><span class=\"s2\">;1m&gt; <\/span><span class=\"nv\">$1<\/span><span class=\"s2\">\\033[0m\"<\/span><span class=\"w\"> <\/span>&gt;&gt;<span class=\"w\"> <\/span><span class=\"nv\">$output<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">log<span class=\"w\"> <\/span><span class=\"s2\">\"Usage: diff.sh &lt;orig&gt; &lt;hacked&gt; &lt;outfile&gt;\"<\/span><\/span>\n<span class=\"code-line\">log<span class=\"w\"> <\/span><span class=\"s2\">\"Tool to find diffrences in two folders, comparing all files\"<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nv\">h<\/span><span class=\"o\">=<\/span><span class=\"si\">${<\/span><span class=\"nv\">2<\/span><span class=\"k\">:-<\/span><span class=\"s2\">\"hacked\"<\/span><span class=\"si\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">o<\/span><span class=\"o\">=<\/span><span class=\"si\">${<\/span><span class=\"nv\">1<\/span><span class=\"k\">:-<\/span><span class=\"s2\">\"original\"<\/span><span class=\"si\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">outfile<\/span><span class=\"o\">={<\/span><span class=\"m\">3<\/span>:-<span class=\"s2\">\"diffout\"<\/span><span class=\"o\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">## Use find and md5sum to get all the files, scan their contents <\/span><\/span>\n<span class=\"code-line\">log<span class=\"w\"> <\/span><span class=\"s2\">\"Scanning directory <\/span><span class=\"nv\">$h<\/span><span class=\"s2\">\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">hmd5<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span>find<span class=\"w\"> <\/span><span class=\"nv\">$h<\/span><span class=\"w\"> <\/span>-type<span class=\"w\"> <\/span>f<span class=\"w\"> <\/span>-exec<span class=\"w\"> <\/span>md5sum<span class=\"w\"> <\/span><span class=\"o\">{}<\/span><span class=\"w\"> <\/span>+<span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>sort<span class=\"w\"> <\/span>-k<span class=\"w\"> <\/span><span class=\"m\">2<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\">log<span class=\"w\"> <\/span><span class=\"s2\">\"Scanning directory <\/span><span class=\"nv\">$o<\/span><span class=\"s2\">\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">omd5<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span>find<span class=\"w\"> <\/span><span class=\"nv\">$o<\/span><span class=\"w\"> <\/span>-type<span class=\"w\"> <\/span>f<span class=\"w\"> <\/span>-exec<span class=\"w\"> <\/span>md5sum<span class=\"w\"> <\/span><span class=\"o\">{}<\/span><span class=\"w\"> <\/span>+<span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>sort<span class=\"w\"> <\/span>-k<span class=\"w\"> <\/span><span class=\"m\">2<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">## vars for progress output<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">totallines<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$hmd5<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>wc<span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>awk<span class=\"w\"> <\/span><span class=\"s1\">'{print $1}'<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">i<\/span><span class=\"o\">=<\/span><span class=\"m\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">last<\/span><span class=\"o\">=<\/span><span class=\"m\">0<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">log<span class=\"w\"> <\/span><span class=\"s2\">\"Diffing (<\/span><span class=\"nv\">$totallines<\/span><span class=\"s2\"> files)\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">## for all files<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">while<\/span><span class=\"w\"> <\/span><span class=\"nv\">IFS<\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">read<\/span><span class=\"w\"> <\/span>-r<span class=\"w\"> <\/span>line<span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">do<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">## remove prefix from the hacked filename<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">hfile<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$line<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>awk<span class=\"w\"> <\/span><span class=\"s1\">'{print $2}'<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">hfile<\/span><span class=\"o\">=<\/span><span class=\"si\">${<\/span><span class=\"nv\">hfile<\/span><span class=\"p\">#<\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$h<\/span><span class=\"s2\">\"<\/span><span class=\"si\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">## find the corresponding file in the original filesystem<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">oline<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$omd5<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>grep<span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"si\">${<\/span><span class=\"nv\">hfile<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">nlines<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$oline<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>wc<span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>awk<span class=\"w\"> <\/span><span class=\"s1\">'{print $1}'<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">stat<\/span><span class=\"o\">=<\/span><span class=\"m\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">## grep may have found 0, 1 (perfect!) or more equivalents (as I can't search for exact matches)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"w\"> <\/span><span class=\"nv\">$nlines<\/span><span class=\"w\"> <\/span>-eq<span class=\"w\"> <\/span><span class=\"m\">0<\/span><span class=\"w\"> <\/span><span class=\"o\">]<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">then<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span>log<span class=\"w\"> <\/span><span class=\"s2\">\"Could not find file <\/span><span class=\"nv\">$hfile<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span>WARN<\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">continue<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">elif<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"w\"> <\/span><span class=\"nv\">$nlines<\/span><span class=\"w\"> <\/span>-gt<span class=\"w\"> <\/span><span class=\"m\">1<\/span><span class=\"w\"> <\/span><span class=\"o\">]<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">then<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">## if it found &gt;1 equivalent, we have to search ourselves<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">while<\/span><span class=\"w\"> <\/span><span class=\"nv\">IFS<\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">read<\/span><span class=\"w\"> <\/span>-r<span class=\"w\"> <\/span>l2<span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">do<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nv\">f<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$l2<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>awk<span class=\"w\"> <\/span><span class=\"s1\">'{print $2}'<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nv\">f<\/span><span class=\"o\">=<\/span><span class=\"si\">${<\/span><span class=\"nv\">f<\/span><span class=\"p\">#<\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$o<\/span><span class=\"s2\">\"<\/span><span class=\"si\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$f<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$hfile<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"o\">]<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">then<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"nv\">oline<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$l2<\/span><span class=\"s2\">\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"nv\">stat<\/span><span class=\"o\">=<\/span><span class=\"m\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"k\">break<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">fi<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">done<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$oline<\/span><span class=\"s2\">\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">## exactly one -&gt; perfect<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nv\">stat<\/span><span class=\"o\">=<\/span><span class=\"m\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">fi<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">## oline=\"\" if grep did not find anything<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">## stat=0 if grep did not find anything or it found &gt;1 file and we did not<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">## find anything ourselves<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$oline<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"\"<\/span><span class=\"w\"> <\/span><span class=\"o\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">||<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"w\"> <\/span><span class=\"nv\">$stat<\/span><span class=\"w\"> <\/span>-eq<span class=\"w\"> <\/span><span class=\"m\">0<\/span><span class=\"w\"> <\/span><span class=\"o\">]<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">then<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span>log<span class=\"w\"> <\/span><span class=\"s2\">\"Did not find file <\/span><span class=\"nv\">$hfile<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span>WARN<\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nv\">hsum<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$line<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>awk<span class=\"w\"> <\/span><span class=\"s1\">'{print $1}'<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nv\">osum<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">echo<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$oline<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"p\">|<\/span><span class=\"w\"> <\/span>awk<span class=\"w\"> <\/span><span class=\"s1\">'{print $1}'<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\"># check the checksum of the original and hacked file<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$osum<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$hsum<\/span><span class=\"s2\">\"<\/span><span class=\"w\"> <\/span><span class=\"o\">]<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">then<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span>:<\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span>log<span class=\"w\"> <\/span><span class=\"s2\">\"Checksums did not check out on '<\/span><span class=\"nv\">$hfile<\/span><span class=\"s2\">'\"<\/span><span class=\"w\"> <\/span><span class=\"nv\">$CHECK<\/span><span class=\"w\"> <\/span><span class=\"nv\">$outfile<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">fi<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">fi<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">## progress output<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">i<\/span><span class=\"o\">=<\/span><span class=\"k\">$((<\/span><span class=\"nv\">i<\/span><span class=\"o\">+<\/span><span class=\"m\">1<\/span><span class=\"k\">))<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nv\">next<\/span><span class=\"o\">=<\/span><span class=\"k\">$((<\/span><span class=\"nv\">last<\/span><span class=\"o\">+<\/span><span class=\"m\">250<\/span><span class=\"k\">))<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"w\"> <\/span><span class=\"nv\">$i<\/span><span class=\"w\"> <\/span>-gt<span class=\"w\"> <\/span><span class=\"nv\">$next<\/span><span class=\"w\"> <\/span><span class=\"o\">]<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"k\">then<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span>log<span class=\"w\"> <\/span><span class=\"s2\">\"progress (<\/span><span class=\"nv\">$i<\/span><span class=\"s2\">\/<\/span><span class=\"nv\">$totallines<\/span><span class=\"s2\"> files)\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nv\">last<\/span><span class=\"o\">=<\/span><span class=\"nv\">$next<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">fi<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">done<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"<\/span><span class=\"nv\">$hmd5<\/span><span class=\"s2\">\"<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"uigetmovieremaiantime\">UI::GetMovieRemaianTime<\/h3>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"err\">001<\/span><span class=\"nf\">b3584<\/span><span class=\"w\"> <\/span><span class=\"err\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"err\">&gt;<\/span><span class=\"p\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3584:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e92d48f0<\/span><span class=\"w\">    <\/span><span class=\"no\">push<\/span><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"no\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">lr<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3588:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e28db014<\/span><span class=\"w\">    <\/span><span class=\"no\">add<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#20<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b358c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24dd088<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#136<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3590:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03b01<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1024<\/span><span class=\"w\">   <\/span><span class=\"c1\">; 0x400<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3594:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3030<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-48<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3598:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3003707<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1799<\/span><span class=\"w\">   <\/span><span class=\"c1\">; 0x707<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b359c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3034<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-52<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffcc<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35a0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a0301e<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#30<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35a4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3038<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-56<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffc8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35a8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03096<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#150<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x96<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35ac:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b303c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-60<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffc4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35b0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03f4b<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#300<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x12c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35b4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3040<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-64<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffc0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35b8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03f96<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#600<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x258<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35bc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3044<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-68<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffbc<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35c0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a0300f<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#15<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35c4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3048<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-72<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffb8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35c8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03007<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#7<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35cc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b304c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-76<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffb4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35d0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3e03102<\/span><span class=\"w\">    <\/span><span class=\"no\">mvn<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-2147483648<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x80000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35d4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3050<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-80<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffb0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35d8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35dc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3080<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-128<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff80<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35e0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35e4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3054<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-84<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffac<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35e8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35ec:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3058<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-88<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35f0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35f4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35f8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b35fc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3600:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3604:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b305c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-92<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3608:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b360c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3060<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-96<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3610:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebff0fff<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">177614<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Storage_Free_Spacev@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3614:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a02000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3618:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b361c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b26fc<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-108<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff94<\/span><\/span>\n<span class=\"code-line\"><span class=\"err\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3620:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebff100e<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">177660<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z28UI_Get_Storage_File_Max_Sizev@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3624:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a02000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3628:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b362c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b27f4<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-116<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff8c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3630:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a02000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3634:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3638:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b22f4<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-36<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffdc<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b363c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3640:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3028<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-40<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3644:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a00053<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#83<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x53<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3648:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed3f2<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168618<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b364c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3650:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3654:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a00050<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#80<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x50<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3658:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed3ee<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168618<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b365c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3660:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b307c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3664:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b007c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3668:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a01000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b366c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">eb001748<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">1b9394<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z22UI_Set_Attr_Movie_Size18eUI_CAP_MOVIE_SIZE@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x1100<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3670:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3674:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3060<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-96<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3678:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b007c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b367c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebffff3c<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">1b3374<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z21UI_Get_Video_Bit_Rate18eUI_CAP_MOVIE_SIZE@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3680:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3684:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3058<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-88<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3688:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24b2084<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#132<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b368c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24b3088<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#136<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3690:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00002<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3694:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01003<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3698:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebffff98<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">1b3500<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z21UI_Get_Audio_Bit_RatePiS_@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b369c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2068<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-104<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff98<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36a0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3070<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-112<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff90<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36a4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36a8:<\/span><span class=\"w\">   <\/span><span class=\"err\">8<\/span><span class=\"nf\">a00000b<\/span><span class=\"w\">    <\/span><span class=\"no\">bhi<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b36dc<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x158<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36ac:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2068<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-104<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff98<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36b0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3070<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-112<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff90<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36b4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36b8:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000011<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3704<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x180<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36bc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b206c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-108<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff94<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36c0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3074<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-116<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff8c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36c4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36c8:<\/span><span class=\"w\">   <\/span><span class=\"err\">8<\/span><span class=\"nf\">a000003<\/span><span class=\"w\">    <\/span><span class=\"no\">bhi<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b36dc<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x158<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36cc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b206c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-108<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff94<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36d0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3074<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-116<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff8c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36d4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36d8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000009<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3704<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x180<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36dc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b27d4<\/span><span class=\"w\">    <\/span><span class=\"no\">ldrd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-116<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff8c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36e0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b22f4<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-36<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffdc<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36e4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b27d4<\/span><span class=\"w\">    <\/span><span class=\"no\">ldrd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-116<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff8c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36e8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01b03<\/span><span class=\"w\">    <\/span><span class=\"no\">lsl<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#22<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36ec:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a06522<\/span><span class=\"w\">    <\/span><span class=\"no\">lsr<\/span><span class=\"w\"> <\/span><span class=\"no\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#10<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36f0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1816006<\/span><span class=\"w\">    <\/span><span class=\"no\">orr<\/span><span class=\"w\"> <\/span><span class=\"no\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r6<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36f4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a07523<\/span><span class=\"w\">    <\/span><span class=\"no\">lsr<\/span><span class=\"w\"> <\/span><span class=\"no\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#10<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36f8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03006<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r6<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b36fc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3028<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-40<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3700:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000008<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3728<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x1a4<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3704:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b26dc<\/span><span class=\"w\">    <\/span><span class=\"no\">ldrd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-108<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff94<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3708:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b22f4<\/span><span class=\"w\">    <\/span><span class=\"no\">strd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-36<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffdc<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b370c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b26dc<\/span><span class=\"w\">    <\/span><span class=\"no\">ldrd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-108<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff94<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3710:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01b03<\/span><span class=\"w\">    <\/span><span class=\"no\">lsl<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#22<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3714:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a04522<\/span><span class=\"w\">    <\/span><span class=\"no\">lsr<\/span><span class=\"w\"> <\/span><span class=\"no\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#10<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3718:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1814004<\/span><span class=\"w\">    <\/span><span class=\"no\">orr<\/span><span class=\"w\"> <\/span><span class=\"no\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b371c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a05523<\/span><span class=\"w\">    <\/span><span class=\"no\">lsr<\/span><span class=\"w\"> <\/span><span class=\"no\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#10<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3720:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03004<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3724:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3028<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-40<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3728:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b372c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b302c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-44<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3730:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a00030<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#48<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x30<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3734:<\/span><span class=\"w\">   <\/span><span class=\"nf\">eb012277<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">1fc118<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_State14eUI_STATE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3738:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b373c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530001<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3740:<\/span><span class=\"w\">   <\/span><span class=\"err\">13<\/span><span class=\"nf\">a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">movne<\/span><span class=\"w\">   <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3744:<\/span><span class=\"w\">   <\/span><span class=\"err\">03<\/span><span class=\"nf\">a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">moveq<\/span><span class=\"w\">   <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3748:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e6ef3073<\/span><span class=\"w\">    <\/span><span class=\"no\">uxtb<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b374c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3750:<\/span><span class=\"w\">   <\/span><span class=\"err\">0<\/span><span class=\"nf\">a00000d<\/span><span class=\"w\">    <\/span><span class=\"no\">beq<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b378c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x208<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3754:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a000c3<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#195<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0xc3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3758:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed3ae<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168618<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b375c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3760:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530001<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3764:<\/span><span class=\"w\">   <\/span><span class=\"err\">13<\/span><span class=\"nf\">a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">movne<\/span><span class=\"w\">   <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3768:<\/span><span class=\"w\">   <\/span><span class=\"err\">03<\/span><span class=\"nf\">a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">moveq<\/span><span class=\"w\">   <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b376c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e6ef3073<\/span><span class=\"w\">    <\/span><span class=\"no\">uxtb<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3770:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3774:<\/span><span class=\"w\">   <\/span><span class=\"err\">0<\/span><span class=\"nf\">a000002<\/span><span class=\"w\">    <\/span><span class=\"no\">beq<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3784<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x200<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3778:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03004<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b377c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b302c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-44<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3780:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000001<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b378c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x208<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3784:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3788:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b302c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-44<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b378c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b26dc<\/span><span class=\"w\">    <\/span><span class=\"no\">ldrd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-108<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff94<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3790:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51bc088<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">ip<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-136<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff78<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3794:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b1060<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-96<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3798:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d1000<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b379c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b102c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-44<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37a0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d1004<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#4<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37a4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00002<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37a8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01003<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37ac:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2058<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-88<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37b0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a0300c<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">ip<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37b4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfadadb<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">6a328<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">mm_util_movie_record_time@plt<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37b8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37bc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b305c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-92<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37c0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e14b22d4<\/span><span class=\"w\">    <\/span><span class=\"no\">ldrd<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-36<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffdc<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37c4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51bc088<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">ip<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-136<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff78<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37c8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b1060<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-96<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37cc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d1000<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37d0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b102c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-44<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37d4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d1004<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#4<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37d8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00002<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37dc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01003<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37e0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2058<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-88<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37e4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a0300c<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">ip<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37e8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfadace<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">6a328<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">mm_util_movie_record_time@plt<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37ec:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37f0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37f4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37f8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b37fc:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000006<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b381c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x298<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3800:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3804:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e2832003<\/span><span class=\"w\">    <\/span><span class=\"no\">add<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3808:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b380c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">b1a03002<\/span><span class=\"w\">    <\/span><span class=\"no\">movlt<\/span><span class=\"w\">   <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3810:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03143<\/span><span class=\"w\">    <\/span><span class=\"no\">asr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3814:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3818:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000007<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b383c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2b8<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b381c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3820:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530001<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3824:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000004<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b383c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2b8<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3828:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b382c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a02fa3<\/span><span class=\"w\">    <\/span><span class=\"no\">lsr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#31<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3830:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e0823003<\/span><span class=\"w\">    <\/span><span class=\"no\">add<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3834:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a030c3<\/span><span class=\"w\">    <\/span><span class=\"no\">asr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3838:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b383c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"err\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3840:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3e03102<\/span><span class=\"w\">    <\/span><span class=\"no\">mvn<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-2147483648<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x80000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3844:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3848:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3858<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2d4<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b384c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3003707<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1799<\/span><span class=\"w\">   <\/span><span class=\"c1\">; 0x707<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3850:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3854:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000001<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3860<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x2dc<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3858:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b385c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3860:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b307c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-124<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff84<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3864:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530007<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#7<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3868:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000039<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3954<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3d0<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b386c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3870:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3874:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000005<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3890<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x30c<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3878:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b387c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530095<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#149<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x95<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3880:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3890<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x30c<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3884:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03096<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#150<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x96<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3888:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b388c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000030<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3954<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3d0<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3890:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3894:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530004<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3898:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000006<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b38b8<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x334<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b389c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38a0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e300312b<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#299<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x12b<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38a4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38a8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b38b8<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x334<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38ac:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03f4b<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#300<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x12c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38b0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38b4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000026<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3954<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3d0<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38b8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38bc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530005<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#5<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38c0:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000006<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b38e0<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x35c<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38c4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38c8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3003257<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#599<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x257<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38cc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1520003<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38d0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b38e0<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x35c<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38d4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03f96<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#600<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x258<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38d8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38dc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea00001c<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3954<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3d0<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38e0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38e4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38e8:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000005<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3904<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x380<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38ec:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38f0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530006<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#6<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38f4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3904<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x380<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38f8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03007<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#7<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b38fc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3900:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000013<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3954<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3d0<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3904:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3908:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530001<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b390c:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000005<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3928<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3a4<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3910:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3914:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e353000e<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#14<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3918:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3928<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3a4<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b391c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a0300f<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#15<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3920:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3924:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea00000a<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3954<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3d0<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3928:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3078<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-120<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff88<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b392c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530002<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3930:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000005<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b394c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3c8<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3934:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3938:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e353001d<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#29<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b393c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">da000002<\/span><span class=\"w\">    <\/span><span class=\"no\">ble<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b394c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3c8<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3940:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a0301e<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#30<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3944:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3948:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000001<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3954<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3d0<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b394c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3018<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-24<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3950:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3954:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3000583<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1411<\/span><span class=\"w\">   <\/span><span class=\"c1\">; 0x583<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3958:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed32e<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168618<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b395c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3960:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3964:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000004<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b397c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x3f8<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3968:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a00e3f<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1008<\/span><span class=\"w\">   <\/span><span class=\"c1\">; 0x3f0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b396c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed329<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168618<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Get_Value14eUI_VALUE_ITEM@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3970:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3974:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e353001f<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#31<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3978:<\/span><span class=\"w\">   <\/span><span class=\"err\">1<\/span><span class=\"nf\">a000001<\/span><span class=\"w\">    <\/span><span class=\"no\">bne<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3984<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x400<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b397c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03001<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3980:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ea000000<\/span><span class=\"w\">    <\/span><span class=\"no\">b<\/span><span class=\"w\">   <\/span><span class=\"mh\">1b3988<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x404<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3984:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3988:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b398c:<\/span><span class=\"w\">   <\/span><span class=\"err\">0<\/span><span class=\"nf\">a000001<\/span><span class=\"w\">    <\/span><span class=\"no\">beq<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3998<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x414<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3990:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3e03102<\/span><span class=\"w\">    <\/span><span class=\"no\">mvn<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-2147483648<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x80000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3994:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3998:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a0007c<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#124<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x7c<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b399c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b101c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39a0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfed36c<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">168758<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z12UI_Set_Value14eUI_VALUE_ITEMi@@Base<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39a4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3003048<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#72<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x48<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39a8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e340304e<\/span><span class=\"w\">    <\/span><span class=\"no\">movt<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#78<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x4e<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39ac:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e5931000<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">r3<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39b0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24b2080<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#128<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x80<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39b4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e30a3790<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#42896<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xa790<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39b8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3403026<\/span><span class=\"w\">    <\/span><span class=\"no\">movt<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#38<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x26<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39bc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d3000<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39c0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b301c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-28<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffe4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39c4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d3004<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#4<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39c8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39cc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d3008<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#8<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39d0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00001<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39d4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a01002<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39d8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e30a2780<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#42880<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xa780<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39dc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3402026<\/span><span class=\"w\">    <\/span><span class=\"no\">movt<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#38<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x26<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39e0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3028<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-40<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffd8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39e4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfadf8c<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">6b81c<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">mm_camcorder_set_attributes@plt<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39e8:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39ec:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3054<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-84<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffac<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39f0:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3054<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-84<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffac<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39f4:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3530000<\/span><span class=\"w\">    <\/span><span class=\"no\">cmp<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39f8:<\/span><span class=\"w\">   <\/span><span class=\"err\">0<\/span><span class=\"nf\">a000012<\/span><span class=\"w\">    <\/span><span class=\"no\">beq<\/span><span class=\"w\"> <\/span><span class=\"mh\">1b3a48<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">_Z25UI_Get_Movie_Remaian_Timev@@Base<\/span><span class=\"p\">+<\/span><span class=\"mi\">0x4c4<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b39fc:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b2080<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-128<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff80<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a00:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e30a37a4<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#42916<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xa7a4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a04:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3403026<\/span><span class=\"w\">    <\/span><span class=\"no\">movt<\/span><span class=\"w\">    <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#38<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x26<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a08:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d3000<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a0c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3054<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-84<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffac<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a10:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d3004<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#4<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a14:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e58d2008<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#8<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a18:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e30a0760<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#42848<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xa760<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a1c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3400026<\/span><span class=\"w\">    <\/span><span class=\"no\">movt<\/span><span class=\"w\">    <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#38<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x26<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a20:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e30b1744<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#46916<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xb744<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a24:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3401026<\/span><span class=\"w\">    <\/span><span class=\"no\">movt<\/span><span class=\"w\">    <\/span><span class=\"no\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#38<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0x26<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a28:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3002251<\/span><span class=\"w\">    <\/span><span class=\"no\">movw<\/span><span class=\"w\">    <\/span><span class=\"no\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#593<\/span><span class=\"w\">    <\/span><span class=\"c1\">; 0x251<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a2c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a30:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfae4ad<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">6ccec<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">slpcam_print_log@plt<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a34:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b3080<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-128<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff80<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a38:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00003<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a3c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">ebfade50<\/span><span class=\"w\">    <\/span><span class=\"no\">bl<\/span><span class=\"w\">  <\/span><span class=\"mh\">6b384<\/span> <span class=\"p\">&lt;<\/span><span class=\"no\">free@plt<\/span><span class=\"p\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a40:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e3a03000<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a44:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e50b3080<\/span><span class=\"w\">    <\/span><span class=\"no\">str<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-128<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"c1\">; 0xffffff80<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a48:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e51b305c<\/span><span class=\"w\">    <\/span><span class=\"no\">ldr<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#-92<\/span><span class=\"p\">]<\/span><span class=\"w\">  <\/span><span class=\"c1\">; 0xffffffa4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a4c:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e1a00003<\/span><span class=\"w\">    <\/span><span class=\"no\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r3<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a50:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e24bd014<\/span><span class=\"w\">    <\/span><span class=\"no\">sub<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#20<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"err\">1<\/span><span class=\"nl\">b3a54:<\/span><span class=\"w\">   <\/span><span class=\"nf\">e8bd88f0<\/span><span class=\"w\">    <\/span><span class=\"no\">pop<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"no\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">fp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"no\">pc<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>","category":[{"@attributes":{"term":"Fotografie"}},{"@attributes":{"term":"Samsung"}},{"@attributes":{"term":"Photography"}},{"@attributes":{"term":"Movie"}},{"@attributes":{"term":"Record"}},{"@attributes":{"term":"DSLM"}},{"@attributes":{"term":"1080p"}},{"@attributes":{"term":"drime4"}},{"@attributes":{"term":"ARM"}},{"@attributes":{"term":"computer science"}},{"@attributes":{"term":"Informatik"}}]},{"title":"Samsung NX300M Mods: Unlimited Movie Length","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/fotografie\/samsung-nx300m-mods-unlimited-movie-length.html","rel":"alternate"}},"published":"2021-03-30T11:45:00+02:00","updated":"2021-03-30T11:45:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2021-03-30:\/fotografie\/samsung-nx300m-mods-unlimited-movie-length.html","summary":"<p>I am currently planning a few video projects and was searching for some cheap, preferably second hand, cameras on-line. I stumbled upon the discontinued NX-line of cameras by Samsung and had a browse through the spec sheets of some of them and found the NX300 and NX300M [<a href=\"https:\/\/www.digitalkamera.de\/Kamera\/Samsung\/NX300M.aspx\">1<\/a>], which are \u2026<\/p>","content":"<p>I am currently planning a few video projects and was searching for some cheap, preferably second hand, cameras on-line. I stumbled upon the discontinued NX-line of cameras by Samsung and had a browse through the spec sheets of some of them and found the NX300 and NX300M [<a href=\"https:\/\/www.digitalkamera.de\/Kamera\/Samsung\/NX300M.aspx\">1<\/a>], which are more or less identical, except the articulating screen of the NX300M has what is known as a selfie-mode.<\/p>\n<p>For me the most interesting properties are that it can shoot 1080p60 video (while 50fps is more useful for me in Germany), it has interchangeable lenses, manual modes and is a DSLM, so you can essentially adapt every old lens onto it, you can find. Unfortunately there are some downsides: It can only shoot 21 minutes (about 4 GiB) of 1080p50\/60 video, the bitrate of that video is not that great, so on higher ISO-values the video gets really blocky and it does not have a microphone input (except a weird proprietary microphone [<a href=\"https:\/\/www.dpreview.com\/forums\/thread\/3989299\">5<\/a>], which sits on the hot shoe. However, for about 100 &euro; per camera these are quite obtainable.<\/p>\n<p>So I've started to poke around with a search engine of my choice and found some very interesting posts by people hacking the Samsung NX300 and NX300M and executing their own code [<a href=\"https:\/\/op-co.de\/blog\/posts\/hacking_the_nx300\/\">2<\/a>,<a href=\"https:\/\/github.com\/ge0rg\/samsung-nx-hacks\">4<\/a>], even for auto-backup over the built-in wifi [<a href=\"https:\/\/lemmster.de\/auto-backup-from-nx300-via-ftp.html\">6<\/a>], getting the source from Samsung [<a href=\"https:\/\/opensource.samsung.com\">7<\/a>] (which is still possible, however you have to ask for it), hacking the firmware to remove the movie length limit [<a href=\"https:\/\/www.dpreview.com\/forums\/post\/56754944\">3<\/a>], and finding the developer menu [[8]], which also has some settings for removing the video limit.<\/p>\n<p>While all of the resources are still on-line, I will be copying them in a few blog posts, when I find something out. First of all: remove the movie limit. That's easy. <\/p>\n<p>You enter the developer menu by putting a file in the root-directory of the SD-Card with the name <code>nx_dev.adj<\/code>. The content has to be <code>smart_camera<\/code>, exactly 12 bytes in length. Make sure, your editor does not add additional bytes at the end, maybe open the file in hexedit or a different hex editor to make absolutely sure. Then you boot up your camera with the SD-Card inside, switch it into AUTO-mode and enter the following: <strong>DOWN<\/strong>, <strong>OK<\/strong>, <strong>UP<\/strong>, <strong>OK<\/strong>, <strong>RIGHT<\/strong>, hold <strong>EV<\/strong>, press and release <strong>OK<\/strong>, release EV. Bosh, you should be in the developer menu.<\/p>\n<p>The only really useful thing here is in the system parameters menu, where you can change the overheat power-off temperature, disable power saving features, disable movie length, disable the need of attaching a lens to the camera (especially useful when dealing with defective cameras) and allow you to capture shots even when the autofocus-system cannot lock on.<\/p>\n<p>I undertook other things and looked into the source code, however have not been able to build an image up until now, and have not looked into the hacked firmware for the NX300 camera. I would love to investigate the microphone input, however I did not come across the external microphone up until now (if you have one and want to get rid of it, email me!), I would like to increase the bitrate, however these properties are buried inside a binary blob and I was not able to reverse engineer the drime4 driver or the MMAL-interface to it. The autoexec.sh does not help me, at least not for now.<\/p>\n<h2 id=\"references\">References<\/h2>\n<p>[1] <a href=\"https:\/\/www.digitalkamera.de\/Kamera\/Samsung\/NX300M.aspx\">https:\/\/www.digitalkamera.de\/Kamera\/Samsung\/NX300M.aspx<\/a><br\/>\n[2] <a href=\"https:\/\/op-co.de\/blog\/posts\/hacking_the_nx300\/\">https:\/\/op-co.de\/blog\/posts\/hacking_the_nx300\/<\/a><br\/>\n[3] <a href=\"https:\/\/www.dpreview.com\/forums\/post\/56754944\">https:\/\/www.dpreview.com\/forums\/post\/56754944<\/a><br\/>\n[4] <a href=\"https:\/\/github.com\/ge0rg\/samsung-nx-hacks\">https:\/\/github.com\/ge0rg\/samsung-nx-hacks<\/a><br\/>\n[5] <a href=\"https:\/\/www.dpreview.com\/forums\/thread\/3989299\">https:\/\/www.dpreview.com\/forums\/thread\/3989299<\/a><br\/>\n[6] <a href=\"https:\/\/lemmster.de\/auto-backup-from-nx300-via-ftp.html\">https:\/\/lemmster.de\/auto-backup-from-nx300-via-ftp.html<\/a><br\/>\n[7] <a href=\"https:\/\/opensource.samsung.com\">https:\/\/opensource.samsung.com<\/a><\/p>","category":[{"@attributes":{"term":"Fotografie"}},{"@attributes":{"term":"Samsung"}},{"@attributes":{"term":"Photography"}},{"@attributes":{"term":"Movie"}},{"@attributes":{"term":"Record"}},{"@attributes":{"term":"DSLM"}},{"@attributes":{"term":"1080p"}},{"@attributes":{"term":"drime4"}}]},{"title":"Using Pelican and Tipue Search for a (Client-Side) Search Function in a Static Website","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/tipue-search-engine.html","rel":"alternate"}},"published":"2020-05-04T21:00:00+02:00","updated":"2020-05-04T21:00:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2020-05-04:\/informatik\/tipue-search-engine.html","summary":"<p>As I'm using a static website generator, in my case Pelican, I'm very limited on the services I can bring to my readers. Every content and page needs to be generated beforehand, no calculations are possible on the server, when the client decides to read an article. So server-side search \u2026<\/p>","content":"<p>As I'm using a static website generator, in my case Pelican, I'm very limited on the services I can bring to my readers. Every content and page needs to be generated beforehand, no calculations are possible on the server, when the client decides to read an article. So server-side search engines are not possible. Therefore a good way is to use a client-side search engine in JavaScript, for example Tipue Search, which is open source and free to use.<\/p>\n<p>The way Tipue works is by loading essentially all the content of your website as JSON into memory and searching on it in JavaScript with a search term, the reader sets, e.g. she types something in a search bar. The Pelican Plugin <code>tipue_search<\/code> allows generating such a file, which loads all the contents of your website into a variable in JavaScript, where Tipue then searches on.<\/p>\n<p>I've just noticied, that I got an older version (5.0 from 2015). I'm assuming this article can still be used for deploying a search function with a more recent version of Tipue Search. The current version is 7.1 [<a href=\"https:\/\/github.com\/getpelican\/pelican-plugins\">1<\/a>]. <\/p>\n<p>Addendum: I've just merged my changes manually into the current 7.1 version. Apart from a few peculiarities, like the related-section behaving oddly, I didn't find any problems (after a decent amount of swearing of course).<\/p>\n<h2 id=\"installation\">Installation<\/h2>\n<h3 id=\"pelican-plugin\">Pelican Plugin<\/h3>\n<p>The Pelican Plugin can be found in the Pelican Plugins Repository [<a href=\"https:\/\/github.com\/getpelican\/pelican-plugins\">1<\/a>]. Installing these plugins is quite easy:<\/p>\n<ol>\n<li>Clone the Repository somewhere into your pelican-folder, e.g. to <code>pelican-plugins<\/code><\/li>\n<li>Append your <code>PLUGINS<\/code> variable in your <code>pelicanconf.py<\/code> with the wanted plugin<\/li>\n<li>Install the prerequisites of the <code>tipue_search<\/code> plugin<\/li>\n<\/ol>\n<p>Cloning the repository is done with <code>git<\/code>, make sure to recursively clone the repo, as there are submodules enabled in this repo:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>git clone --recursive https:\/\/github.com\/getpelican\/pelican-plugins<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Then update your <code>pelicanconf.py<\/code> to denote the directory(ies) of your plugins and denote every plugin you want to use. I'm using <code>better_codeblock_line_numbering<\/code>, <code>css-html-js-minify<\/code> and <code>tipue_search<\/code>.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">PLUGIN_PATHS<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span> <span class=\"s2\">\"pelican-plugins\"<\/span> <span class=\"p\">]<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">PLUGINS<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span> <span class=\"s2\">\"better_codeblock_line_numbering\"<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'css-html-js-minify'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'tipue_search'<\/span> <span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">TIPUE_SEARCH<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">True<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">TEMPLATE_PAGES<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\">    <span class=\"s1\">'search.html'<\/span><span class=\"p\">:<\/span> <span class=\"s1\">'search.html'<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Then you only need to install the prerequisites of your plugins, in the case of <code>tipue_search<\/code> it is the Python-module <code>beautifulsoup4<\/code>. Make sure to install it for the same Python version your Pelican installation uses (you may want to use pip3 on your distribution).<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>pip install beautifulsoup4<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Then you should be good to go. When you run Pelican (for example by using the Makefile), you will find a <code>tipuesearch_content.js<\/code> in your output-directory.<\/p>\n<h3 id=\"the-javascript-part\">The JavaScript part<\/h3>\n<ol>\n<li>Create a new template for your search page<\/li>\n<li>Download and include tipue search and jQuery if you havent<\/li>\n<\/ol>\n<p>Now create a new template <code>search.html<\/code>. For starters it should feature a search bar and an area for the results. Make sure you include the Tipue Search-Javascript files and your content-file. You will also need jQuery in your website, as Tipue Search is based on jQuery (but that requirement should be removable quite easily with some JavaScript knowledge).<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">{%<\/span> <span class=\"k\">extends<\/span> <span class=\"s2\">\"base.html\"<\/span> <span class=\"cp\">%}<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">{%<\/span> <span class=\"k\">block<\/span> <span class=\"nv\">title<\/span> <span class=\"cp\">%}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span>Durchsuche<span class=\"w\"> <\/span><span class=\"cp\">{{<\/span> <span class=\"nb\">super<\/span><span class=\"o\">()<\/span> <span class=\"cp\">}}<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">{%<\/span> <span class=\"k\">endblock<\/span> <span class=\"nv\">title<\/span> <span class=\"cp\">%}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">{%<\/span> <span class=\"k\">block<\/span> <span class=\"nv\">extra_head<\/span> <span class=\"cp\">%}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"nt\">&lt;link<\/span><span class=\"w\"> <\/span><span class=\"na\">rel=<\/span><span class=\"s\">\"stylesheet\"<\/span><span class=\"w\"> <\/span><span class=\"na\">type=<\/span><span class=\"s\">\"text\/css\"<\/span><span class=\"w\"> <\/span><span class=\"na\">href=<\/span><span class=\"s\">\"\/static\/css\/tipuesearch.css\"<\/span><span class=\"nt\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"nt\">&lt;script<\/span><span class=\"w\"> <\/span><span class=\"na\">src=<\/span><span class=\"s\">\"\/tipuesearch_content.js\"<\/span><span class=\"nt\">&gt;&lt;\/script&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"nt\">&lt;script<\/span><span class=\"w\"> <\/span><span class=\"na\">src=<\/span><span class=\"s\">\"\/static\/js\/tipuesearch_set.js\"<\/span><span class=\"nt\">&gt;&lt;\/script&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"nt\">&lt;script<\/span><span class=\"w\"> <\/span><span class=\"na\">src=<\/span><span class=\"s\">\"\/static\/js\/tipuesearch.min.js\"<\/span><span class=\"nt\">&gt;&lt;\/script&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"nt\">&lt;script&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>$(document).ready(function()<span class=\"w\"> <\/span>{<\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span>$('#tipue_search_input').tipuesearch({<\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span>'show':<span class=\"w\"> <\/span>10,<span class=\"w\">               <\/span>\/\/<span class=\"w\"> <\/span>shows<span class=\"w\"> <\/span>10<span class=\"w\"> <\/span>found<span class=\"w\"> <\/span>entries<\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span>'descriptiveWords':<span class=\"w\"> <\/span>75,<span class=\"w\">   <\/span>\/\/<span class=\"w\"> <\/span>shows<span class=\"w\"> <\/span>75<span class=\"w\"> <\/span>words<span class=\"w\"> <\/span>of<span class=\"w\"> <\/span>teaser<span class=\"w\"> <\/span>text<\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span>'newWindow':<span class=\"w\"> <\/span>false,<span class=\"w\">       <\/span>\/\/<span class=\"w\"> <\/span>don't<span class=\"w\"> <\/span>open<span class=\"w\"> <\/span>a<span class=\"w\"> <\/span>new<span class=\"w\"> <\/span>window,<span class=\"w\"> <\/span>when<span class=\"w\"> <\/span>clicking<span class=\"w\"> <\/span>a<span class=\"w\"> <\/span>result<\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span>});<\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span>});<\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"nt\">&lt;\/script&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">{%<\/span> <span class=\"k\">endblock<\/span> <span class=\"cp\">%}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">{%<\/span> <span class=\"k\">block<\/span> <span class=\"nv\">content<\/span> <span class=\"cp\">%}<\/span><\/span>\n<span class=\"code-line\"><span class=\"nt\">&lt;h1&gt;<\/span>Durchsuchen<span class=\"nt\">&lt;\/h1&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nt\">&lt;form<\/span><span class=\"w\"> <\/span><span class=\"na\">action=<\/span><span class=\"s\">\"search.html\"<\/span><span class=\"nt\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nt\">&lt;div<\/span><span class=\"w\"> <\/span><span class=\"na\">class=<\/span><span class=\"s\">\"tipue_search_group\"<\/span><span class=\"nt\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nt\">&lt;input<\/span><span class=\"w\"> <\/span><span class=\"na\">type=<\/span><span class=\"s\">\"text\"<\/span><span class=\"w\"> <\/span><span class=\"na\">name=<\/span><span class=\"s\">\"q\"<\/span><span class=\"w\"> <\/span><span class=\"na\">id=<\/span><span class=\"s\">\"tipue_search_input\"<\/span><span class=\"nt\">&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nt\">&lt;\/div&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nt\">&lt;\/form&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nt\">&lt;div&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nt\">&lt;div<\/span><span class=\"w\"> <\/span><span class=\"na\">id=<\/span><span class=\"s\">\"tipue_search_content\"<\/span><span class=\"nt\">&gt;&lt;\/div&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nt\">&lt;\/div&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">{%<\/span> <span class=\"k\">endblock<\/span> <span class=\"nv\">content<\/span> <span class=\"cp\">%}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>You will at least need the <code>tipue_search_input<\/code>-input as your search bar and the <code>tipue_search_content<\/code>-div as the area where to place the results. The default is that a URI-parameter is used as input for te search script. The <code>tipuesearch_set.js<\/code> contains some strings and skipped words, you may want to fill out. It's in English and you may want to translate it to your primary language.<\/p>\n<h2 id=\"my-changes_1\">My Changes<\/h2>\n<p>I've modified both, the pelican plugin as well as the JavaScript and CSS stuff, as I wasn't happy with the default behaviour.<\/p>\n<h3 id=\"pelican-plugin_1\">Pelican Plugin<\/h3>\n<p>I've modified the behaviour of the Pelican Plugin a bit. For one I wasn't satisfied with the way it handled categories (not at all), it didn't include thumbnails or dates, and called tags categories. Therefore I changed the <code>create_json_node<\/code> function to the following:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>    <span class=\"k\">def<\/span><span class=\"w\"> <\/span><span class=\"nf\">create_json_node<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">page<\/span><span class=\"p\">):<\/span><\/code><\/span>\n<span class=\"code-line\">        <span class=\"k\">if<\/span> <span class=\"nb\">getattr<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'status'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'published'<\/span><span class=\"p\">)<\/span> <span class=\"o\">!=<\/span> <span class=\"s1\">'published'<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\">            <span class=\"k\">return<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">soup_title<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BeautifulSoup<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">title<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&amp;nbsp;'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">' '<\/span><span class=\"p\">),<\/span> <span class=\"s1\">'html.parser'<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_title<\/span> <span class=\"o\">=<\/span> <span class=\"n\">soup_title<\/span><span class=\"o\">.<\/span><span class=\"n\">get_text<\/span><span class=\"p\">(<\/span><span class=\"s1\">' '<\/span><span class=\"p\">,<\/span> <span class=\"n\">strip<\/span><span class=\"o\">=<\/span><span class=\"kc\">True<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&ldquo;'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\"'<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_title<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page_title<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&rdquo;'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\"'<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&rsquo;'<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"'\"<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_title<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page_title<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'^'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'&amp;#94;'<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">soup_text<\/span> <span class=\"o\">=<\/span> <span class=\"n\">BeautifulSoup<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">content<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'html.parser'<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_text<\/span> <span class=\"o\">=<\/span> <span class=\"n\">soup_text<\/span><span class=\"o\">.<\/span><span class=\"n\">get_text<\/span><span class=\"p\">(<\/span><span class=\"s1\">' '<\/span><span class=\"p\">,<\/span> <span class=\"n\">strip<\/span><span class=\"o\">=<\/span><span class=\"kc\">True<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&ldquo;'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\"'<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_text<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page_text<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&rdquo;'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'\"'<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&rsquo;'<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"'\"<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_text<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page_text<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'&para;'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">' '<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">replace<\/span><span class=\"p\">(<\/span><span class=\"s1\">'^'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'&amp;#94;'<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_text<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">' '<\/span><span class=\"o\">.<\/span><span class=\"n\">join<\/span><span class=\"p\">(<\/span><span class=\"n\">page_text<\/span><span class=\"o\">.<\/span><span class=\"n\">split<\/span><span class=\"p\">())<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_category<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">category<\/span><span class=\"o\">.<\/span><span class=\"n\">name<\/span> <span class=\"k\">if<\/span> <span class=\"nb\">getattr<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'category'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'None'<\/span><span class=\"p\">)<\/span> <span class=\"o\">!=<\/span> <span class=\"s1\">'None'<\/span> <span class=\"k\">else<\/span> <span class=\"s1\">''<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">tags<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">tags<\/span> <span class=\"k\">if<\/span> <span class=\"nb\">getattr<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'tags'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'None'<\/span><span class=\"p\">)<\/span> <span class=\"o\">!=<\/span> <span class=\"s1\">'None'<\/span> <span class=\"k\">else<\/span> <span class=\"s1\">''<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_tags<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\">        <span class=\"k\">for<\/span> <span class=\"n\">t<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">tags<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\">            <span class=\"n\">page_tags<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">t<\/span><span class=\"o\">.<\/span><span class=\"n\">name<\/span> <span class=\"o\">+<\/span> <span class=\"s2\">\",\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_tags<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page_tags<\/span><span class=\"p\">[:<\/span><span class=\"o\">-<\/span><span class=\"mi\">1<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_thumbnail<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"\/data\/thumbnail\/\"<\/span> <span class=\"o\">+<\/span> <\/span>\n<span class=\"code-line\">            <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">thumbnail<\/span> <span class=\"o\">+<\/span> <span class=\"s2\">\"_large.jpg\"<\/span> <span class=\"k\">if<\/span> <span class=\"nb\">getattr<\/span><span class=\"p\">(<\/span><span class=\"n\">page<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'thumbnail'<\/span><span class=\"p\">,<\/span> <span class=\"s1\">'None'<\/span> <span class=\"p\">)<\/span> <span class=\"o\">!=<\/span> <span class=\"s1\">'None'<\/span> <span class=\"k\">else<\/span> <span class=\"s1\">''<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_date<\/span> <span class=\"o\">=<\/span> <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">date<\/span><span class=\"o\">.<\/span><span class=\"n\">strftime<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"<\/span><span class=\"si\">%d<\/span><span class=\"s2\">.%m.%Y\"<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">page_url<\/span> <span class=\"o\">=<\/span> <span class=\"s1\">'.'<\/span><\/span>\n<span class=\"code-line\">        <span class=\"k\">if<\/span> <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">url<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\">            <span class=\"k\">if<\/span> <span class=\"s2\">\"pages\/\"<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">url<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\">                <span class=\"n\">page_url<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"\/\"<\/span> <span class=\"o\">+<\/span> <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">url<\/span><\/span>\n<span class=\"code-line\">            <span class=\"k\">else<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\">                <span class=\"n\">page_url<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">\"\/\"<\/span> <span class=\"o\">+<\/span> <span class=\"n\">page_category<\/span><span class=\"o\">.<\/span><span class=\"n\">lower<\/span><span class=\"p\">()<\/span> <span class=\"o\">+<\/span> <span class=\"s2\">\"\/\"<\/span> <span class=\"o\">+<\/span> <span class=\"n\">page<\/span><span class=\"o\">.<\/span><span class=\"n\">url<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">        <span class=\"n\">node<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span><span class=\"s1\">'title'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_title<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\">                <span class=\"s1\">'text'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_text<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\">                <span class=\"s1\">'category'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_category<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\">                <span class=\"s1\">'tags'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_tags<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\">                <span class=\"s1\">'url'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_url<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\">                <span class=\"s1\">'thumbnail'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_thumbnail<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\">                <span class=\"s1\">'date'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_date<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\">                <span class=\"s1\">'loc'<\/span><span class=\"p\">:<\/span> <span class=\"n\">page_url<\/span><span class=\"p\">}<\/span> <\/span>\n<span class=\"code-line\">        <span class=\"bp\">self<\/span><span class=\"o\">.<\/span><span class=\"n\">json_nodes<\/span><span class=\"o\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">node<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>I still am thinking about changing the <code>page_text<\/code> handling as well. I'm not happy with all my blog entries in one JSON-readable format. Also this could make problems on slower internet connections for huge blogs.<\/p>\n<h4 id=\"troubles-with-css-html-js-minify\">Troubles with css-html-js-minify<\/h4>\n<p>I found, that using the minification plugin css-html-js-minify results in an unreadable <code>tipuesearch_content.js<\/code>-file. So I've also altered the output-path and move the file in my Makefile after pelican has run and has created by website.<\/p>\n<h3 id=\"javascript_1\">JavaScript<\/h3>\n<p>While I left the search logic completely intact for the time being. I did however remove options and functions I didn't intend on using. Also I modified the output. In a single file, which holds about 600 lines of JavaScript code, Tipue searches in the content-area, sorts the results according to a score and outputs the resulting HTML-code to a variable <code>out<\/code>.<\/p>\n<p>The behaviour is configurable by setting options on whether some things should be displayed or not. However the order cannot be altered. Also the default pagination is a the bottom, I wanted it to be placed on both sides. These are the options (on the older 5.0 version). They can be found in <code>tipuesearch.js<\/code> on the very top.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">$<\/span><span class=\"p\">.<\/span><span class=\"nx\">extend<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'show'<\/span><span class=\"w\">                   <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"mf\">7<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'newWindow'<\/span><span class=\"w\">              <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">false<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'showURL'<\/span><span class=\"w\">                <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'showTitleCount'<\/span><span class=\"w\">         <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'minimumLength'<\/span><span class=\"w\">          <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"mf\">3<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'descriptiveWords'<\/span><span class=\"w\">       <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"mf\">25<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'highlightTerms'<\/span><span class=\"w\">         <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">true<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'highlightEveryTerm'<\/span><span class=\"w\">     <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">false<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'mode'<\/span><span class=\"w\">                   <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"s1\">'static'<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'liveDescription'<\/span><span class=\"w\">        <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"s1\">'*'<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'liveContent'<\/span><span class=\"w\">            <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"s1\">'*'<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'contentLocation'<\/span><span class=\"w\">        <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"s1\">'tipuesearch\/tipuesearch_content.json'<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'debug'<\/span><span class=\"w\">                  <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"kc\">false<\/span><span class=\"w\">          <\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"nx\">options<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This is my altered output-part <code>tipuesearch.js<\/code>:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ last unaltered line:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nx\">found<\/span><span class=\"p\">.<\/span><span class=\"nx\">sort<\/span><span class=\"p\">(<\/span><span class=\"kd\">function<\/span><span class=\"p\">(<\/span><span class=\"nx\">a<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nx\">b<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"nx\">b<\/span><span class=\"p\">.<\/span><span class=\"nx\">score<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"w\"> <\/span><span class=\"nx\">a<\/span><span class=\"p\">.<\/span><span class=\"nx\">score<\/span><span class=\"w\"> <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ is the count (c) of the found-array is bigger then the configured number of shown results<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ -&gt; generate pagination<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">c<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">pages<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nx\">ceil<\/span><span class=\"p\">(<\/span><span class=\"nx\">c<\/span><span class=\"w\"> <\/span><span class=\"o\">\/<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">page<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"w\"> <\/span><span class=\"o\">\/<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;div id=\"pagination\" style=\"text-align:center;margin-bottom: 10px\"&gt;'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"mf\">0<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span class=\"pagination_element prev\"&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">            &lt;a data-id=\"'<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"s1\">'_'<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"nx\">replace<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"s1\">'\"&gt;&laquo;&lt;\/a&gt;&lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span class=\"pagination_element_disabled\"&gt;&laquo;&lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">page<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;=<\/span><span class=\"w\"> <\/span><span class=\"mf\">2<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">p_b<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">pages<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">pages<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"mf\">3<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nx\">p_b<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mf\">3<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mf\">0<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">p_b<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"nx\">page<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span class=\"pagination_element pagination_element_active\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"o\">+<\/span><span class=\"mf\">1<\/span><span class=\"p\">)<\/span><span class=\"o\">+<\/span><span class=\"s1\">'&lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span class=\"pagination_element\"&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">                    &lt;a data-id=\"'<\/span><span class=\"o\">+<\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"o\">*<\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"p\">)<\/span><span class=\"o\">+<\/span><span class=\"s1\">'_'<\/span><span class=\"o\">+<\/span><span class=\"nx\">replace<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"o\">+<\/span><span class=\"mf\">1<\/span><span class=\"p\">)<\/span><span class=\"o\">+<\/span><span class=\"s1\">'&lt;\/a&gt;&lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">p_b<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">page<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"mf\">2<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">p_b<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">pages<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nx\">p_b<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">pages<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">page<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"w\"> <\/span><span class=\"mf\">1<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">p_b<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"nx\">page<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span class=\"pagination_element pagination_element_active\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"o\">+<\/span><span class=\"mf\">1<\/span><span class=\"p\">)<\/span><span class=\"o\">+<\/span><span class=\"s1\">'&lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">                    &lt;a class=\"tipue_search_foot_box\" data-id=\"'<\/span><span class=\"o\">+<\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"o\">*<\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"p\">)<\/span><span class=\"o\">+<\/span><span class=\"s1\">'_'<\/span><span class=\"o\">+<\/span><span class=\"nx\">replace<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"p\">(<\/span><span class=\"nx\">f<\/span><span class=\"o\">+<\/span><span class=\"mf\">1<\/span><span class=\"p\">)<\/span><span class=\"o\">+<\/span><span class=\"s1\">'&lt;\/a&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">                &lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">page<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"mf\">1<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"nx\">pages<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span class=\"next pagination_element\"&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">            &lt;a data-id=\"'<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"s1\">'_'<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"nx\">replace<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"s1\">'\"&gt;&raquo;&lt;\/a&gt;&lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;span class=\"next pagination_element_disabled\"&gt;&raquo;&lt;\/span&gt;'<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nx\">pagination<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;\/div&gt;'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ add a top pagination bit to the output<\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">out<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"nx\">pagination<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ iterate over the sorted found-array<\/span><\/span>\n<span class=\"code-line\"><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">l_o<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mf\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">i<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mf\">0<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">i<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">found<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">i<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">l_o<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;=<\/span><span class=\"w\"> <\/span><span class=\"nx\">start<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;&amp;<\/span><span class=\"w\"> <\/span><span class=\"nx\">l_o<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">show<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"nx\">start<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">t<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">found<\/span><span class=\"p\">[<\/span><span class=\"nx\">i<\/span><span class=\"p\">].<\/span><span class=\"nx\">desc<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">t_d<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s1\">''<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">t_w<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">t<\/span><span class=\"p\">.<\/span><span class=\"nx\">split<\/span><span class=\"p\">(<\/span><span class=\"s1\">' '<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">t_w<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">descriptiveWords<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nx\">t_d<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"mf\">0<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"w\"> <\/span><span class=\"nx\">set<\/span><span class=\"p\">.<\/span><span class=\"nx\">descriptiveWords<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"nx\">t_d<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"nx\">t_w<\/span><span class=\"p\">[<\/span><span class=\"nx\">f<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"s1\">' '<\/span><span class=\"p\">;<\/span><span class=\"w\">    <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">t_d<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">$<\/span><span class=\"p\">.<\/span><span class=\"nx\">trim<\/span><span class=\"p\">(<\/span><span class=\"nx\">t_d<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">t_d<\/span><span class=\"p\">.<\/span><span class=\"nx\">charAt<\/span><span class=\"p\">(<\/span><span class=\"nx\">t_d<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"w\"> <\/span><span class=\"mf\">1<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'.'<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nx\">t_d<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">' ...'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">f<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">found<\/span><span class=\"p\">[<\/span><span class=\"nx\">i<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">out<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"s1\">'&lt;article class=\"post-preview\"&gt;&lt;div class=\"post-inner post-hover\"&gt;&lt;div class=\"post-thumbnail\"&gt;'<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">thumbnail<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"mf\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nx\">out<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;a href=\"'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">url<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\" title=\"'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">title<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\" class=\"hover_img\"&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">                &lt;div style=\"background-image:url(\\''<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">thumbnail<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\\')\" class=\"thumb-medium\"&gt;&lt;\/div&gt;&lt;\/a&gt;&lt;\/div&gt;'<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">category<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"mf\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"nx\">out<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;div class=\"post-meta group\"&gt;&lt;span class=\"post-category\"&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">                &lt;a href=\"\/category\/'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">category<\/span><span class=\"o\">+<\/span><span class=\"s1\">'.html\" rel=\"category tag\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">category<\/span><span class=\"o\">+<\/span><span class=\"s1\">'&lt;\/a&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">            &lt;\/span&gt;&lt;span class=\"post-date\"&gt;&lt;time class=\"published updated\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">date<\/span><span class=\"o\">+<\/span><span class=\"s1\">'&lt;\/time&gt;&lt;\/span&gt;&lt;\/div&gt;'<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"nx\">out<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"s1\">'&lt;a href=\"'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">url<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\" rel=\"bookmark\" title=\"'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">title<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\"&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">            &lt;h2 class=\"post-title entry-title\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">title<\/span><span class=\"o\">+<\/span><span class=\"s1\">'&lt;\/h2&gt;&lt;\/a&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">            &lt;div class=\"entry excerpt entry-summary\"&gt;'<\/span><span class=\"o\">+<\/span><span class=\"nx\">t_d<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">            &lt;div class=\"readmore\"&gt;&lt;a href=\"'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">url<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\" title=\"'<\/span><span class=\"o\">+<\/span><span class=\"nx\">f<\/span><span class=\"p\">.<\/span><span class=\"nx\">title<\/span><span class=\"o\">+<\/span><span class=\"s1\">'\"&gt;[weiter lesen]&lt;\/a&gt;\\<\/span><\/span>\n<span class=\"code-line\"><span class=\"s1\">            &lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/article&gt;'<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nx\">l_o<\/span><span class=\"o\">++<\/span><span class=\"p\">;<\/span><span class=\"w\">     <\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ add a bottom pagination bit<\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">out<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"nx\">pagination<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h1>Conclusion<\/h1>\n<p>With a few more modifcations to the way Tipue Search works, e.g. binding it to keyup on the search-bar instead of relying on a q-parameter to the website, makes it quite usable. A few flaws and bugs will have creeped through, but I have now a working search engine in my statically generated blog.<\/p>\n<p>As a reference I'll leave the plugin and my JavaScript files here. Please use them with a grain of salt - it is way safer to just use the upstream version, especially when you are finding this article in a few years!<\/p>\n<ul>\n<li><a href=\"\/static\/resources\/tipue_search_plugin.tar.gz\">Modified Pelican Plugin<\/a><\/li>\n<li><a href=\"\/static\/resources\/tipue_search_js.tar.gz\">Modified JavaScript Files<\/a><\/li>\n<\/ul>\n<h1>References<\/h1>\n<p>[1] <a href=\"https:\/\/github.com\/getpelican\/pelican-plugins\">https:\/\/github.com\/getpelican\/pelican-plugins<\/a><br\/>\n[2] <a href=\"https:\/\/tipue.com\/search\/\">https:\/\/tipue.com\/search\/<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"continuous integration"}},{"@attributes":{"term":"pelican"}},{"@attributes":{"term":"tipue search"}},{"@attributes":{"term":"search"}},{"@attributes":{"term":"find"}},{"@attributes":{"term":"static website"}},{"@attributes":{"term":"client side"}},{"@attributes":{"term":"javascript"}}]},{"title":"My very own Continuous Integration Server (mvoCI)","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/mvoci-introduction.html","rel":"alternate"}},"published":"2020-01-11T16:30:00+01:00","updated":"2020-01-11T16:30:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2020-01-11:\/informatik\/mvoci-introduction.html","summary":"<p><strong>This article has been deprecated by Golangs Modules.<\/strong><\/p>\n<p>About a year ago, I changed by website (which you are visiting right about now) from a Wordpress based system to a static website generator called <em>Pelican<\/em> [<a href=\"https:\/\/www.getpelican.com\">pelican<\/a>]. Since then I feared building that website and that it may become one day \u2026<\/p>","content":"<p><strong>This article has been deprecated by Golangs Modules.<\/strong><\/p>\n<p>About a year ago, I changed by website (which you are visiting right about now) from a Wordpress based system to a static website generator called <em>Pelican<\/em> [<a href=\"https:\/\/www.getpelican.com\">pelican<\/a>]. Since then I feared building that website and that it may become one day not buildable, e.g. because I loose the knowledge on how to build the damn thing. Also deploying new versions of the website would be quite a hassle, as the new HTML-files would have been copied over to the server manually.<\/p>\n<p>But fear not! There are solutions to that, in the form of continuous integration servers. Well... I tried <em>Jenkins<\/em> [<a href=\"https:\/\/jenkins.org\">jenkins<\/a>]. Jenkins is a really powerful Java-software, which can do nearly anything you want. However, it is a Java-software. Once it has got its heap-memory, it will never give it back. This would be swell, if the server running it has enough RAM to spare, however my vServer has only 2 GB. And Jenkins after building my website once (a quite simple website, I might add) ate nearly half of it. Jenkins alone! After an incident, where Jenkins spammed a log-file and also ate the disk-space, I swiftly got rid of it.<\/p>\n<p>There are also other Continuous Integration servers, but most of them are quite overblown and full of features I would never need. A very simple one is <em>flux-ci<\/em> [<a href=\"https:\/\/github.com\/NiklasRosenstein\/flux-ci\">flux-ci<\/a>]. It's written in Python, based on Flask and is an easy to use, straightforward solution to my problem. Looking through the code at the time (about a year back), I wasn't satisfied and began work to modify flux-ci to my hearts content. Eventually I stopped to work on that code, and began programming my very own CI-server (mvoCI).<\/p>\n<p>While it shares the templates, i.e. the optics with flux-ci (I've asked), it is its very own beast, written in Go [<a href=\"https:\/\/www.golang.org\">golang<\/a>], based on <em>echo<\/em> and <em>gorm<\/em> for object-oriented interface to a relational database.<\/p>\n<h2 id=\"what-can-it-do\">What can it do?<\/h2>\n<p><em>tl;dr:<\/em><\/p>\n<ul>\n<li>build git repositories on user input or repo-push<\/li>\n<li>public repositories (builds can be viewed and artifacts downloaded without auth)<\/li>\n<li>query information about repos and builds, as well as build specific branches and commits via a REST API<\/li>\n<li>deploy e.g. a pelican website by abusing the build-script<\/li>\n<\/ul>\n<p>I tried to stay on the simple side with mvoCI. It can build your git-repository, either when you hit build, or when someone pushes into the repository, if you have a webhook configured in the git-server of your choice. I personally use <em>gitea<\/em> [<a href=\"https:\/\/gitea.io\">gitea<\/a>] in conjunction with that.<\/p>\n<p>You can have several users, with their own repositories. You can have repositories, which are public, i.e. their builds can be downloaded without authentication. I recently added a REST-API interface, which can be used to query information about repos and builds, and to build a specific repository, commit and branch. More work needs to be done, so someone could be able to build an accompanying app to mvoCI in the future.<\/p>\n<p>I already use mvoCI to deploy new versions of my website. Essentially I am abusing locality; the user executing mvoCI has write access to the folder of the website. After building the website, its www-folder is copied over to the apache DocumentRoot. Deployment of simple services via this technique seems possible. For deploying services or updates over the boundaries of machines the API could be used; this is part of the work to be done in future.<\/p>\n<h3 id=\"what-is-planned\">What is planned?<\/h3>\n<p>At the time of writing, the API is a bit bare bones. While querying information is already possible, it is not possible to edit information or delete any objects. Also querying if there are any new builds for a repository or even push-notifications if that is the case it not possible yet.<\/p>\n<h4 id=\"webhook-filters\">Webhook-Filters<\/h4>\n<p>An idea in a semi-abandoned state is the introduction of filters for webhooks. Git-Servers send an event-type with their webhook, so they can indicate, whether the user pushed into the repository of created a new release or whatever. A idea is extend the quite simple model of a repository, with one single build script, to a repo with a list of filters and attached build scripts. So a repo could \"listen\" to several events and handle them differently, maybe even building the repo several times for a single webhook event. <\/p>\n<p>A generic filter-interface would also allow to do timed builds on more frequented repositories, think about Firefox, where you would want automatic tests for every commit, but maybe would want a release-build only every night or week. A pattern-based method for keeping builds would fit right into that.<\/p>\n<p>This would indeed make mvoCI more powerful, but also bigger and would require a rewrite of some parts of the code, which I'm not willing to do yet. I've started work on it and may be restarting it in the future, however at the moment, mvoCI is more than capable of handling what I want from it.<\/p>\n<h2 id=\"how-do-i-get-it_2\">How do I get it?<\/h2>\n<h3 id=\"tldr\">tl;dr<\/h3>\n<p>Make sure you have at least the go-toolchain in version 1.12.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"ch\">#!\/bin\/bash<\/span><\/code><\/span>\n<span class=\"code-line\">git<span class=\"w\"> <\/span>clone<span class=\"w\"> <\/span>https:\/\/git.stefannaumann.de\/snaums\/mvoCI.git<\/span>\n<span class=\"code-line\"><span class=\"nb\">cd<\/span><span class=\"w\"> <\/span>mvoCI<\/span>\n<span class=\"code-line\"><span class=\"nb\">export<\/span><span class=\"w\"> <\/span><span class=\"nv\">GOPATH<\/span><span class=\"o\">=<\/span><span class=\"k\">$(<\/span><span class=\"nb\">pwd<\/span><span class=\"k\">)<\/span><\/span>\n<span class=\"code-line\">mkdir<span class=\"w\"> <\/span>-p<span class=\"w\"> <\/span>src\/mvoCI<\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\"># move the code to the go-dir<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">shopt<\/span><span class=\"w\"> <\/span>-s<span class=\"w\"> <\/span>extglob<span class=\"w\"> <\/span>dotglob<\/span>\n<span class=\"code-line\">mv<span class=\"w\"> <\/span>!<span class=\"o\">(<\/span>src<span class=\"o\">)<\/span><span class=\"w\"> <\/span>src\/mvoCI\/<\/span>\n<span class=\"code-line\"><span class=\"nb\">shopt<\/span><span class=\"w\"> <\/span>-u<span class=\"w\"> <\/span>dotglob<\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nb\">pushd<\/span><span class=\"w\"> <\/span>src\/mvoCI<\/span>\n<span class=\"code-line\"><span class=\"c1\"># install build dependencies<\/span><\/span>\n<span class=\"code-line\">make<span class=\"w\"> <\/span>dep<\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\"># build and move artifacts to dist<\/span><\/span>\n<span class=\"code-line\">make<span class=\"w\"> <\/span>dist<\/span>\n<span class=\"code-line\"><span class=\"c1\"># cleanup<\/span><\/span>\n<span class=\"code-line\">rm<span class=\"w\"> <\/span>-rf<span class=\"w\"> <\/span>web<span class=\"w\"> <\/span>hook<span class=\"w\"> <\/span>log<span class=\"w\"> <\/span>Makefile<span class=\"w\"> <\/span>main.go<span class=\"w\"> <\/span>mvo.cfg<span class=\"w\"> <\/span>static<span class=\"w\"> <\/span>repo<span class=\"w\"> <\/span>static<span class=\"w\"> <\/span>views<span class=\"w\"> <\/span>core<span class=\"w\"> <\/span>build<span class=\"w\"> <\/span>builds<\/span>\n<span class=\"code-line\"><span class=\"nb\">popd<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\"># cleanup for packaging<\/span><\/span>\n<span class=\"code-line\">mv<span class=\"w\"> <\/span>src\/mvoCI\/dist\/*<span class=\"w\"> <\/span>.<\/span>\n<span class=\"code-line\">rm<span class=\"w\"> <\/span>-rf<span class=\"w\"> <\/span>src<span class=\"w\"> <\/span>pkg<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"the-long-version\">The long version<\/h3>\n<p>I'm currently testing building and packaging mvoCI with my own mvoCI instance. Until I make that public, the script under tl;dr is sufficient to build mvoCI. <\/p>\n<p>The code is hosted on my <a href=\"https:\/\/git.stefannaumann.de\/snaums\/mvoCI\">gitea-instance<\/a>. Clone the repository and move inside. <\/p>\n<h4 id=\"requirements\">Requirements<\/h4>\n<ul>\n<li>golang in version 1.12 or higher<\/li>\n<\/ul>\n<p>If you haven't gotten the go toolchain in the correct version, you can install it from the Linux repositories. Make sure you get at least version 1.12. If you are running Debian 10 (stable), you will not get the correct version. You can get a working toolchain from [<a href=\"https:\/\/golang.org\/dl\/\">golang-dl<\/a>] in that circumstance or when running Windows or Mac OSX.<\/p>\n<h4 id=\"build-time-requirements\">Build time requirements<\/h4>\n<p>As of time of writing mvoCI depends on the following golang-libraries<\/p>\n<ul>\n<li>github.com\/jinzhu\/gorm <em>(plus it's dependencies for DB access)<\/em><\/li>\n<li>github.com\/labstack\/echo<\/li>\n<li>golang.org\/x\/crypto\/bcrypt<\/li>\n<li>github.com\/foolin\/goview<\/li>\n<li>github.com\/foolin\/goview\/supports\/echoview-v4<\/li>\n<\/ul>\n<p>If you don't want to bother, just run <code>make dep<\/code>, which will install all necessary library dependencies. If you notice any problems, don't hesitate to contact me.<\/p>\n<h4 id=\"building-mvoci\">Building mvoCI<\/h4>\n<p>Make sure it is in your <code>$GOPATH<\/code>. Either you move the cloned repository to <code>~\/go\/src\/mvoCI<\/code> (which would be the default <code>$GOPATH<\/code>) or you overwrite the environment variable. Make sure you keep the tree intact, i.e. <code>$GOPATH\/src\/mvoCI\/&lt;repo content&gt;<\/code>. You will need to redownload the dependencies into the correct <code>$GOPATH<\/code>. <\/p>\n<p>Change in the directory and run <code>make mvobuild<\/code> or <code>make dist<\/code> . Both will build mvoCI, but <code>dist<\/code> will move all necessary files to the <code>dist<\/code> folder, so you only need to move that to where you want and can start running the application.<\/p>\n<h2 id=\"set-up-and-usage_2\">Set-up and Usage<\/h2>\n<h3 id=\"security\">Security<\/h3>\n<p>Keep in mind, that mvoCI can execute arbitrary bash-code on your machine. If you are running it on your most valuable server, make sure you know what you are doing and keep locked down, so it cannot destroy any other services your machine provides.<\/p>\n<p>At least execute it as a different user from any other. Create a new user, give it a home, copy the <code>dist<\/code> folder into that. Then you could use systemd to execute the program with the correct user at startup. You may use this config file for systemd:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">[Unit]<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"na\">Description<\/span><span class=\"o\">=<\/span><span class=\"s\">mvoCI<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">After<\/span><span class=\"o\">=<\/span><span class=\"s\">syslog.target<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">After<\/span><span class=\"o\">=<\/span><span class=\"s\">network.target<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">After<\/span><span class=\"o\">=<\/span><span class=\"s\">mysqld.service<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">#After=postgresql.service<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">[Service]<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">RestartSec<\/span><span class=\"o\">=<\/span><span class=\"s\">2s<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">Type<\/span><span class=\"o\">=<\/span><span class=\"s\">simple<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">User<\/span><span class=\"o\">=<\/span><span class=\"s\">mvo<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">Group<\/span><span class=\"o\">=<\/span><span class=\"s\">mvo<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">WorkingDirectory<\/span><span class=\"o\">=<\/span><span class=\"s\">\/home\/mvo<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">ExecStart<\/span><span class=\"o\">=<\/span><span class=\"s\">\/home\/mvo\/mvo<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">Restart<\/span><span class=\"o\">=<\/span><span class=\"s\">always<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">Environment<\/span><span class=\"o\">=<\/span><span class=\"s\">USER=mvo HOME=\/home\/mvo<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">[Install]<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">WantedBy<\/span><span class=\"o\">=<\/span><span class=\"s\">multi-user.target<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"installing\">Installing<\/h3>\n<p>For the first installation you will need to run the <code>mvo<\/code> executable with the parameter <code>--install<\/code>. This will set the program in Installation-mode. This allows you to set the database parameters and credentials for the first user. It will create a config file <code>mvo.cfg<\/code>. After the installation process is done, stop the process and run the program without any parameters for production. <\/p>\n<p>See through the configuration options in <code>mvo.cfg<\/code>. It's a JSON-representation of the struct in <code>core\/config.go<\/code>. Changing anything will require a restart of the application.<\/p>\n<h3 id=\"running\">Running<\/h3>\n<p>Once it is set-up and running you can login with your credentials, create repositories and new users. You can also LoginTokens, for using the API. An API-call needs a valid token in the <code>mvoCi_session<\/code> token.<\/p>\n<h2 id=\"what-to-do-next_1\">What to do next<\/h2>\n<p>That is up to you. I'd appreciate bug-reports and pull requests to be reported at the <a href=\"http:\/\/git.stefannaumann.de\/snaums\/mvoCI\">repository<\/a>. Every polite feedback is good input, what to improve. This includes feature-requests as well as bug-reports. <\/p>\n<h2 id=\"references\">References<\/h2>\n<p>[flux-ci] <a href=\"https:\/\/github.com\/NiklasRosenstein\/flux-ci\">https:\/\/github.com\/NiklasRosenstein\/flux-ci<\/a><br\/>\n[jenkins] <a href=\"https:\/\/jenkins.io\">https:\/\/jenkins.io<\/a><br\/>\n[gitea] <a href=\"https:\/\/gitea.io\">https:\/\/gitea.io<\/a><br\/>\n[golang] <a href=\"https:\/\/www.golang.org\">https:\/\/www.golang.org<\/a><br\/>\n[golang-dl] <a href=\"https:\/\/golang.org\/dl\/\">https:\/\/golang.org\/dl\/<\/a><br\/>\n[pelican] <a href=\"https:\/\/www.getpelican.com\">https:\/\/www.getpelican.com<\/a><br\/>\n[repository] <a href=\"http:\/\/git.stefannaumann.de\/snaums\/mvoCI\">http:\/\/git.stefannaumann.de\/snaums\/mvoCI<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"golang"}},{"@attributes":{"term":"continuous integration"}},{"@attributes":{"term":"my very own"}},{"@attributes":{"term":"mvoCI"}},{"@attributes":{"term":"CI"}},{"@attributes":{"term":"jenkins"}},{"@attributes":{"term":"pelican"}},{"@attributes":{"term":"git"}},{"@attributes":{"term":"building"}}]},{"title":"Learning COBOL with Examples - Part 2: FILE I\/O","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/learning-cobol-with-examples-02.html","rel":"alternate"}},"published":"2019-03-03T19:00:00+01:00","updated":"2019-03-03T19:00:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2019-03-03:\/informatik\/learning-cobol-with-examples-02.html","summary":"<p>The previous post in this series was about learning the basics of the COBOL programming language. Now I will cover a very important and essential part of COBOL - File Input \/ Output (I\/O). I find it really interesting, as I haven't seen any other language which makes it that easy \u2026<\/p>","content":"<p>The previous post in this series was about learning the basics of the COBOL programming language. Now I will cover a very important and essential part of COBOL - File Input \/ Output (I\/O). I find it really interesting, as I haven't seen any other language which makes it that easy to read files for lines and break them up basically automatically. I suspect, that this is the reason COBOL exists and that most of the business applications did that a lot. <\/p>\n<p>Well nowadays there is basically everything for COBOL, you can write web-services in COBOL, query databases with SQL and do loads more, as we will see in future posts.<\/p>\n<p>The thumbnail is takes from Wiktionary [<a href=\"https:\/\/de.wiktionary.org\/wiki\/Stechuhr\">1<\/a>] by User Ludek [<a href=\"https:\/\/commons.wikimedia.org\/wiki\/User:Ludek\">2<\/a>].<\/p>\n<h2 id=\"file-io\">File I\/O<\/h2>\n<p>In programming files are basically containers of input- or output-data. In Linux, or Unix-Systems for that matter, files can also be pipes or sockets, which can be used to communicate with other programs. In this post I will only discuss opening, reading, writing and closing known files, i.e. using system calls to find files, or list them, is not part of this post. <\/p>\n<p>There are basically four operations you want to do on files. Opening a file tells the Operating System to find the file on the disk, and make it accessible from your application. Internally the so called file descriptor of that file is added to the list of file descriptors of your process. This file descriptor can be used in languages like C for syscalls such as <code>read<\/code>. Closing a file tells the OS, that we are finished, the written content can be flushed to the disk, and the operation with this file is done. <\/p>\n<p>Reading and writing from and to the file does exactly that. A read gets some data from that file and makes it usable via memory regions or variables, whereas writing data takes your variables or a memory region and transfers it into the file, at the current location of the file pointer. However writing is most of the times not immediate, but deferred, i.e. the operation is put off, until more data is there to write to the disk. <\/p>\n<h2 id=\"the-example-program\">The example program<\/h2>\n<p>Take this example program I wrote year ago. It is supposed to read a file containing my worked hours per day, reformats the data and calculates a sum of the worked hours. It is an extremely simple program, but still it is loads of text in COBOL. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">IDENTIFICATION<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kr\">PROGRAM-ID<\/span><span class=\"p\">.<\/span><span class=\"w\"> <\/span><span class=\"nv\">wrkhrs<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kr\">ENVIRONMENT<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">INPUT-OUTPUT<\/span><span class=\"w\"> <\/span><span class=\"kr\">SECTION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">FILE-CONTROL<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kp\">select<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kp\">assign<\/span><span class=\"w\"> <\/span><span class=\"kp\">to <\/span><span class=\"s2\">\"hours.txt\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kp\">organization<\/span><span class=\"w\"> <\/span><span class=\"kp\">is<\/span><span class=\"w\"> <\/span><span class=\"kp\">line<\/span><span class=\"w\"> <\/span><span class=\"kp\">sequential<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kp\">select<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kp\">assign<\/span><span class=\"w\"> <\/span><span class=\"kp\">to <\/span><span class=\"s2\">\"hours.out\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kp\">organization<\/span><span class=\"w\"> <\/span><span class=\"kp\">is<\/span><span class=\"w\"> <\/span><span class=\"kp\">line<\/span><span class=\"w\"> <\/span><span class=\"kp\">sequential<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kr\">DATA<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">FILE<\/span><span class=\"w\"> <\/span><span class=\"kr\">SECTION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">fd<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">hrs-record<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">d<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">Z9<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"kp\">FILLER<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">dayname<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"kp\">FILLER<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"kp\">FILLER<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">6<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">descr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">50<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">fd<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">hrs-out-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">dayname<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">a<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">d<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">b<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">7<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">c<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">15<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">descr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">50<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">total-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">s<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">14<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">total<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kr\">WORKING-STORAGE<\/span><span class=\"w\"> <\/span><span class=\"kr\">SECTION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">ls<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">d<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">99<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">dayname<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">99<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">descr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">50<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">nmbr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">9<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kr\">PROCEDURE<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">bg<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">OPEN<\/span><span class=\"w\"> <\/span><span class=\"kp\">INPUT<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">OPEN<\/span><span class=\"w\"> <\/span><span class=\"kp\">OUTPUT<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"no\">zeroes<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">nmbr<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE <\/span><span class=\"s2\">\", \"<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">a<\/span><span class=\"w\"> <\/span><span class=\"kp\">of<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE <\/span><span class=\"s2\">\" Sep.: \"<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">b<\/span><span class=\"w\"> <\/span><span class=\"kp\">of<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE <\/span><span class=\"s2\">\" hrs., Report: \"<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">c<\/span><span class=\"w\"> <\/span><span class=\"kp\">of<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nv\">reed<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">READ<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs<\/span><span class=\"w\"> <\/span><span class=\"kp\">RECORD<\/span><span class=\"w\"> <\/span><span class=\"kp\">AT<\/span><span class=\"w\"> <\/span><span class=\"kr\">END<\/span><span class=\"w\"> <\/span><span class=\"kr\">go<\/span><span class=\"w\"> <\/span><span class=\"kp\">to<\/span><span class=\"w\"> <\/span><span class=\"nf\">e<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"kp\">CORR<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-record<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">ls<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">ADD<\/span><span class=\"w\"> <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kp\">OF<\/span><span class=\"w\"> <\/span><span class=\"nv\">ls<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">nmbr<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"kp\">CORR<\/span><span class=\"w\"> <\/span><span class=\"nv\">ls<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">WRITE<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">go<\/span><span class=\"w\"> <\/span><span class=\"kp\">to<\/span><span class=\"w\"> <\/span><span class=\"nv\">reed<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nf\">e<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE <\/span><span class=\"s2\">\" Hours total: \"<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">s<\/span><span class=\"w\"> <\/span><span class=\"kp\">OF<\/span><span class=\"w\"> <\/span><span class=\"nv\">total-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"nv\">nmbr<\/span><span class=\"w\"> <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">total<\/span><span class=\"w\"> <\/span><span class=\"kp\">OF<\/span><span class=\"w\"> <\/span><span class=\"nv\">total-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">WRITE<\/span><span class=\"w\"> <\/span><span class=\"nv\">total-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">CLOSE<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">CLOSE<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">STOP<\/span><span class=\"w\"> <\/span><span class=\"kp\">RUN<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"environment-division\">Environment Division<\/h3>\n<p>The environment division contains the Input-Output Section, which in turns holds the file-control-paragraphs. Here the two files, one for writing, one for reading is declared. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kp\">select<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kp\">assign<\/span><span class=\"w\"> <\/span><span class=\"kp\">to <\/span><span class=\"s2\">\"hours.txt\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kp\">organization<\/span><span class=\"w\"> <\/span><span class=\"kp\">is<\/span><span class=\"w\"> <\/span><span class=\"kp\">line<\/span><span class=\"w\"> <\/span><span class=\"kp\">sequential<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Here the name <code>hrs<\/code> is chosen, by which this file will be refered to in the remainder of the program. The name is assigned to the path <code>hours.txt<\/code> and it is organized as lines, i.e. every record is finished with a newline-symbol. This also tells COBOL, that the file is text-based and not a binary file. <code>sequential<\/code> identifies the access pattern, i.e. in what order the file is read or written to. Other valid access patterns would be <code>random<\/code> or <code>dynamic<\/code>.<\/p>\n<p>Both files are handled identically here, as COBOL makes in this part of the program no difference of input- or output-files. <\/p>\n<h3 id=\"data-division\">Data Division<\/h3>\n<p>The data division contains two sections: the file section and the working-storage section. You should already know the working-storage section if you read the previous post, that is. <\/p>\n<h4 id=\"file-section\">File Section<\/h4>\n<p>In the file section, records are defined. This is in my eyes a special point of COBOL, as it lets you define data structures explicitely for working with files and I\/O in particular. There are three data structures defined here.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">fd<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"mi\">01 <\/span><span class=\"nv\">hrs-record<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">d<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">Z9<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"kp\">FILLER<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">dayname<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"kp\">FILLER<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"kp\">FILLER<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">6<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">descr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">50<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The data structure <code>hrs-record<\/code> is defined for use with the file <code>hrs<\/code>. The definition of the variables and fields is identical to what it would be in the working-storage section. The keyword <code>FILLER<\/code> however is something special. It basically serves as a placeholder, as you want the Space in line 3 for example, but you don't you to access it every. So one can use the \"name\" <code>FILLER<\/code> to let the compiler know, that I will never access it and I don't want any name registered with this field of the record. This means I can use it more than once in my program.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">fd<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-out<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"mi\">01 <\/span><span class=\"nv\">hrs-out-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">dayname<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">a<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">2<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">d<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">b<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">7<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">c<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">15<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">descr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">50<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">01 <\/span><span class=\"nv\">total-rec<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">s<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">14<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">total<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The second file will contain two records. They can just be written directly one after the other and both will be usable with the file. <\/p>\n<p>One thing to note is, the records defined here are all characters, that means we cannot do any calculations on them. You could in theory defined certain fields as a numeric value. I always found it more easy to copy the data twice, when needing input and output of records, so I relied on the casting-mechanisms of COBOL. <\/p>\n<h4 id=\"working-storage-section\">Working-Storage Section<\/h4>\n<p>The working storage section describes the variables used in the program. In this case there is <code>nmbr<\/code> used for calculating the total number of hours worked in the month and we have <code>ls<\/code>, which is basically the working-copy of the input record. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"mi\">01 <\/span><span class=\"nv\">ls<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">d<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">99<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">dayname<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">XX<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">99<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">descr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">50<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"mi\">01 <\/span><span class=\"nv\">nmbr<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">9<\/span><span class=\"p\">(<\/span><span class=\"mi\">3<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"procedure-division_1\">Procedure Division<\/h3>\n<p>The procedure division consists of three paragraphs. The <code>bg<\/code> paragraph is the begin of the program, which opens the two files and initialises the data structures. <code>reed<\/code> reads the next record from the input file, does some reformatting and outputs the output-record to the output file. <code>e<\/code> is the end of the program and write the totally worked hours to the output-file. <\/p>\n<h4 id=\"opening-files\">Opening Files<\/h4>\n<p>A file, which has previously been declared under File-Control in the Environment Division, can simply be opened by using the <code>OPEN<\/code> verb.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">OPEN <\/span><span class=\"o\">&lt;<\/span><span class=\"kp\">mode<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">file<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>For simplicity some arguments are omitted. The mode can be one of the four:\n- <code>INPUT<\/code> -- the file can only be read from\n- <code>OUTPUT<\/code> -- the file can only be written to, the file will be created if not present, or emptied if present\n- <code>I-O<\/code> -- the file can be read from and written to\n- <code>EXTEND<\/code> -- the file can be written to, the file-pointer is placed after the last logical record of the file. It can only be used with <code>sequential<\/code> access patterns. <\/p>\n<p>In our case, one file is opened as input, one as output. <\/p>\n<h4 id=\"reading-from-files\">Reading from files<\/h4>\n<p>Reading from files is as simple as calling <code>READ<\/code> with the file handle afterwards. However the <code>READ<\/code> verb can loads of things, for example it can divert the control flow if the end of the file is reached, for example for jumping to a different place or for setting a variable. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">READ <\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">file<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"err\">[<\/span><span class=\"kp\">INTO <\/span><span class=\"o\">&lt;<\/span><span class=\"nv\">data-structure<\/span><span class=\"o\">&gt;<\/span><span class=\"err\">]<\/span><span class=\"w\"> <\/span><span class=\"err\">[<\/span><span class=\"kp\">AT<\/span><span class=\"w\"> <\/span><span class=\"kr\">END <\/span><span class=\"o\">&lt;<\/span><span class=\"err\">statement<\/span><span class=\"o\">&gt;<\/span><span class=\"err\">]<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>When reading a file, where several data structure are attached to, the <code>INTO<\/code> clause can be used to identify the record, which should be filled. <code>AT END<\/code> specifies the statement, which should be executed at the end of the file.<\/p>\n<p>If you want to read a file until the end, one way is to use <code>goto<\/code> in the <code>AT END<\/code> clause of the <code>READ<\/code> verb. However a different approach is using a <code>PERFORM<\/code> loop.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"mi\">0 <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">feof<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kr\">PERFORM<\/span><span class=\"w\"> <\/span><span class=\"kp\">UNTIL<\/span><span class=\"w\"> <\/span><span class=\"nv\">feof<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">    <\/span><span class=\"kr\">READ<\/span><span class=\"w\"> <\/span><span class=\"nv\">hours<\/span><span class=\"w\"> <\/span><span class=\"kp\">RECORD<\/span><span class=\"w\"> <\/span><span class=\"kp\">INTO<\/span><span class=\"w\"> <\/span><span class=\"nv\">hrs-record<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"kp\">AT<\/span><span class=\"w\"> <\/span><span class=\"kr\">END<\/span><span class=\"w\"> <\/span><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"mi\">1 <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">feof<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">END-READ<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">    <\/span><span class=\"c\">*&gt; do stuff<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">END-PERFORM<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>In this case the variable <code>feof<\/code> needs to be declared in the working-storage section. <code>PERFOM<\/code> loops until the condition is true, so until <code>feof<\/code> is bigger than 0. This will happen as soon as the end of the file is found. This way at least one could go around the use of <code>goto<\/code>. Please note, that the only period is followed <code>END-PERFORM<\/code>, as the sentence does not end until the <code>PERFORM<\/code>-loop is finished. <\/p>\n<h4 id=\"writing-a-record-to-file\">Writing a record to file<\/h4>\n<p>Writing is also as simple as using <code>WRITE<\/code>. There are parameters for the <code>WRITE<\/code>-verb, but you will probably know when you need to use one. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">WRITE <\/span><span class=\"o\">&lt;<\/span><span class=\"nv\">record-name<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h4 id=\"closing-a-file\">Closing a file<\/h4>\n<p>Closing a file is done via the <code>CLOSE<\/code> verb, which takes the file handle as parameter.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">CLOSE <\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">file<\/span><span class=\"o\">&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"so-what-does-it-do_1\">So what does it do?<\/h3>\n<p>The example program, which we have dived through, takes an input file which is essentially formatted like that:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"mf\">01<\/span><span class=\"w\"> <\/span><span class=\"n\">Fr<\/span><span class=\"w\"> <\/span><span class=\"mf\">12<\/span><span class=\"w\"> <\/span><span class=\"n\">hrs<\/span><span class=\"mf\">.<\/span><span class=\"w\"> <\/span><span class=\"n\">Really<\/span><span class=\"w\"> <\/span><span class=\"kr\">go<\/span><span class=\"n\">od<\/span><span class=\"mf\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"mf\">02<\/span><span class=\"w\"> <\/span><span class=\"n\">Sa<\/span><span class=\"w\"> <\/span><span class=\"mf\">32<\/span><span class=\"w\"> <\/span><span class=\"n\">hrs<\/span><span class=\"mf\">.<\/span><span class=\"w\"> <\/span><span class=\"n\">Even<\/span><span class=\"w\"> <\/span><span class=\"n\">better<\/span><span class=\"err\">!<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The program reformats it and prints the reformatted text alongside the total number of hours into an output-file:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>Fr, 01 Sep.: 12 hrs., Report: Really good.<\/code><\/span>\n<span class=\"code-line\">Sa, 02 Sep.: 32 hrs., Report: Even better!<\/span>\n<span class=\"code-line\"> Hours total: 044<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>When I wrote this program it was apparently September. This program of course is of limited use, but nontheless I extended it quite a bit, to even give me input-files for gnuplot and create reports of how long I've worked in a month. <\/p>\n<h2 id=\"conclusion_1\">Conclusion<\/h2>\n<p>In a way I find it quite interesting, that COBOL gives me the tools to work with files as input and output this easily. I've not seen any other language which makes it that easy for me to read and write files. C-structs would be similar, but I have to check first, where the newline symbol is myself, and that's a huge hassle. At least I have found one thing COBOL seems to be quite good at. <\/p>\n<h2 id=\"references\">References<\/h2>\n<p>[1] <a href=\"https:\/\/de.wiktionary.org\/wiki\/Stechuhr\">https:\/\/de.wiktionary.org\/wiki\/Stechuhr<\/a><br\/>\n[2] <a href=\"https:\/\/commons.wikimedia.org\/wiki\/User:Ludek\">https:\/\/commons.wikimedia.org\/wiki\/User:Ludek<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"COBOL"}},{"@attributes":{"term":"Programming"}},{"@attributes":{"term":"Tutorial"}}]},{"title":"Learning COBOL with Examples - Part 1: Basics and Hello World","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/learning-cobol-with-examples-01.html","rel":"alternate"}},"published":"2019-02-04T20:08:00+01:00","updated":"2019-02-04T20:08:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2019-02-04:\/informatik\/learning-cobol-with-examples-01.html","summary":"<p>Learning a new programming language and specially a really really old and obscure one is hard. This is especially true with COBOL since most documentation is extremely old, outdated and there are essentially no other users. This means just searching for your problem on any arbitrary search engine will probably \u2026<\/p>","content":"<p>Learning a new programming language and specially a really really old and obscure one is hard. This is especially true with COBOL since most documentation is extremely old, outdated and there are essentially no other users. This means just searching for your problem on any arbitrary search engine will probably not solve your issue, like it would with C or C++ problems. However learning a new language can also be fun and is educational, as there are many old programs out there written in COBOL. <\/p>\n<p>These upcoming blog entries and this one is there to help get you off the ground. I'm not saying, that COBOL is my favourite language and I'm not saying that my code it good. But I still hope these posts will help you understand some basics of the COBOL language. I'm gonna spare you the historic parts. <\/p>\n<p>I'm a C programmer. My background is in Operating Systems and bare-metal programming. <\/p>\n<p>The thumbnail-image is from [<a href=\"http:\/\/deacademic.com\/dic.nsf\/dewiki\/873823\">3<\/a>].<\/p>\n<h2 id=\"compiler\">Compiler<\/h2>\n<p>You will need a compiler, which translates the COBOL source code into natively executeable programs. I'm using GnuCOBOL [<a href=\"https:\/\/open-cobol.sourceforge.io\/\">1<\/a>]. On their website they also have handy reference sheets if you ever need to look up the grammar of COBOL. The Forum on SourceForge is also one of the only places you find people asking for COBOL related problems. <\/p>\n<p>In Arch Linux, gnu-cobol is not in the official repositories, but it can be found in an AUR [<a href=\"https:\/\/aur.archlinux.org\/packages\/gnu-cobol\/\">2<\/a>]. Your distribution will probably also have a package ready for gnu-cobol. <\/p>\n<p>I'm going to use a few flags as default, unless stated otherwise. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>cobc -x --free --Wall inputfile.cob<\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The ''-x'' instructs the compiler to create an executable file. ''--free'' will make it use the free form of COBOL. Old versions of COBOL used a set form on punch cards, where the first so-and-so characters where the line number, then a special field for comments, code, bla. To make COBOL look more like a modern-ish programming language I'm going to use the free form, so I'm able to have very long lines and start at column 0. And ''--Wall'' will print out all warning messages the compiler can produce. This will help improving our code. <\/p>\n<h2 id=\"a-first-very-very-simple-program\">A first very very simple program<\/h2>\n<p>This is a simple program, displaying \"Hello World\" and the truth about everything. It is more than a normal \"Hello World\" program to show you more Divisions of a COBOL program. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">IDENTIFICATION<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kr\">PROGRAM-ID<\/span><span class=\"p\">.<\/span><span class=\"w\"> <\/span><span class=\"nv\">truth<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kr\">ENVIRONMENT<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">CONFIGURATION<\/span><span class=\"w\"> <\/span><span class=\"kr\">SECTION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kp\">SOURCE-COMPUTER<\/span><span class=\"p\">.<\/span><span class=\"w\"> <\/span><span class=\"nv\">IBM-PC<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kp\">OBJECT-COMPUTER<\/span><span class=\"p\">.<\/span><span class=\"w\"> <\/span><span class=\"nv\">IBM-PC<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kr\">DATA<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">WORKING-STORAGE<\/span><span class=\"w\"> <\/span><span class=\"kr\">SECTION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">truth<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">99<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kr\">PROCEDURE<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">begin<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">DISPLAY <\/span><span class=\"s2\">\"Hello World\"<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"mi\">42 <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">truth<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">DISPLAY<\/span><span class=\"w\"> <\/span><span class=\"nv\">truth<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">EXIT<\/span><span class=\"w\"> <\/span><span class=\"kp\">PROGRAM<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The first things, that will probably hit your eye is the fact, that the code is divided into so called Divisions. In Divisions you have Sections, then Paragraphs, Sentences, Verbs and Characters. COBOL was designed to be quite close to the English language, so you will probably understand most of the operations already. <\/p>\n<p>You see four divisions in the code above:<\/p>\n<ol>\n<li>IDENTIFICATION DIVISION - for identifying the program. There is not much of use in there today. The PROGRAM-ID has to be set to be usable from other programs (a topic for another time). <\/li>\n<li>ENVIRONMENT DIVISION - for identifying the environment. The configuration section is there for defining source and target computers. This is not really relevant anymore and can be left out of your programs easily. However the Environment division will be used later for File I\/O. <\/li>\n<li>DATA DIVISION - your variables and data structures will be defined here (inside the WORKING-STORAGE SECTION). <\/li>\n<li>PROCEDURE DIVISION - this is where the actual code is. <\/li>\n<\/ol>\n<h3 id=\"defining-some-variables-data-division\">Defining some Variables (Data Division)<\/h3>\n<p>In the program above the DATA DIVISION and the PROCEDURE DIVISION is interesting. Let's start with the DATA DIVISION, as I am defined a variable in there, named ''truth''. When defining data structures, the syntax is as follows:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"o\">&lt;<\/span><span class=\"k\">level<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"n\">name<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"n\">PIC<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"n\">IS<\/span><span class=\"o\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"n\">type<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"o\">[<\/span><span class=\"n\">VALUE [IS<\/span><span class=\"o\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"k\">value<\/span><span class=\"o\">&gt;<\/span><span class=\"err\">]<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>There are more statements, that can be made, but they are omitted here. COBOL works a bit differently when describing data structures than other languages. Basically nearly everything in COBOL is a record (or struct). The level indicates, which level this entry is on. You can have anything from 01 to 49, 66, 77 and 88 in there. <\/p>\n<table>\n<thead>\n<tr>\n<th>Level<\/th>\n<th>Meaning<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>01<\/td>\n<td>record level, top level<\/td>\n<\/tr>\n<tr>\n<td>02-49<\/td>\n<td>elementary and sub-types<\/td>\n<\/tr>\n<tr>\n<td>66<\/td>\n<td>rename clause<\/td>\n<\/tr>\n<tr>\n<td>77<\/td>\n<td>items, which cannot be sub-divided<\/td>\n<\/tr>\n<tr>\n<td>88<\/td>\n<td>condition name entry<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Let's focus on the levels 01 to 49. With the level one can create deeper data structures. Smaller numbers are names for the group of variables of the next lower numbers. For example one can build a structure as follows:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">DATA<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kr\">WORKING-STORAGE<\/span><span class=\"w\"> <\/span><span class=\"kr\">SECTION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">person<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">name<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"nv\">X<\/span><span class=\"p\">(<\/span><span class=\"mi\">20<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"mi\">02 <\/span><span class=\"nv\">tel<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">9<\/span><span class=\"p\">(<\/span><span class=\"mi\">10<\/span><span class=\"p\">).<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The name is any arbitrary name you want to give to the variable. The PIC clause identifies the data type of the variable. A variable in COBOL is always compounded. You can have one of always the same types, but you can define ones with several different types in different positions, so you can have numbers with signs or decide where the comma is. But you have to do that statically. <\/p>\n<p>So let's say you want to define a variable, which can store a year with four numbers, then the following could a valid definition. Both of the statements are identical. <\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">DATA<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kr\">WORKING-STORAGE<\/span><span class=\"w\"> <\/span><span class=\"kr\">SECTION<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">year<\/span><span class=\"w\">  <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">9999<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"mi\">01 <\/span><span class=\"nv\">year2<\/span><span class=\"w\"> <\/span><span class=\"kt\">PIC IS<\/span><span class=\"w\"> <\/span><span class=\"mi\">9<\/span><span class=\"p\">(<\/span><span class=\"mi\">4<\/span><span class=\"p\">).<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Now if you know other programming languages already, the notation is a bit weird. There is no data type, is there? Oh, yes, there is. But it is written down differently than in C. As said, the PIC-clause determines the type of the variable. The following types are available:<\/p>\n<table>\n<thead>\n<tr>\n<th>Symbol<\/th>\n<th>Meaning<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>9<\/td>\n<td>Numeric<\/td>\n<\/tr>\n<tr>\n<td>A<\/td>\n<td>Alphabetic<\/td>\n<\/tr>\n<tr>\n<td>P<\/td>\n<td>Decimal<\/td>\n<\/tr>\n<tr>\n<td>S<\/td>\n<td>Sign<\/td>\n<\/tr>\n<tr>\n<td>V<\/td>\n<td>Decimal point (implicit)<\/td>\n<\/tr>\n<tr>\n<td>X<\/td>\n<td>Alphanumeric<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Among other things, there is a VALUE-clause after PIC, there can be even more. The VALUE clause sets a preset value, the variable will have when the program starts. <\/p>\n<h3 id=\"writing-a-program-procedure-division\">Writing a Program (Procedure Division)<\/h3>\n<p>Now let's take a gander at the Procedure Division of the above example.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">PROCEDURE<\/span><span class=\"w\"> <\/span><span class=\"kr\">DIVISION<\/span><span class=\"p\">.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nv\">begin<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">DISPLAY <\/span><span class=\"s2\">\"Hello World\"<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">MOVE<\/span><span class=\"w\"> <\/span><span class=\"mi\">42 <\/span><span class=\"kp\">TO<\/span><span class=\"w\"> <\/span><span class=\"nv\">truth<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">DISPLAY<\/span><span class=\"w\"> <\/span><span class=\"nv\">truth<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kr\">STOP<\/span><span class=\"w\"> <\/span><span class=\"kp\">RUN<\/span><span class=\"p\">.<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>It consists of two notable things - the first is the label ''begin''. This is a label like one might know from Assembly-code or really really bad C-code. This allows your code to jump to that exact place with the help of the ''GO TO'' verb. But more on that later. <\/p>\n<p>Then the statements basically look the same. There is a Verb and an\/several operand\/s. ''DISPLAY'' will print the string\/object after it to stdout, ''MOVE'' is a copying operator, like the ''mov''-instruction in most ISAs. The direction of the move is written clearly in the rest of the sentence. ''42 TO truth'' - so you probably already knew what this sentence did, before reading this far. ''STOP RUN'' stops the program, much like ''exit()'' in C. <\/p>\n<p>There are loads of Verbs and Builtin function in modern COBOL, so listing them all here is not only redundant but also nearly impossible. <\/p>\n<h3 id=\"comments\">Comments<\/h3>\n<p>One really important thing are comments. While being omitted in the above example, one can use the following syntax to comment lines.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c\">*&gt; This is a comment, which will be ignored by the compiler<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kr\">DISPLAY <\/span><span class=\"s2\">\"HELLO WORLD\"<\/span><span class=\"w\"> <\/span><span class=\"c\">*&gt; Now Display will be compiled, but this comment not<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"conclusion_1\">Conclusion<\/h2>\n<p>So there we have it. This post showed a very simple COBOL program and tried to describe the concepts generically. If you find errors, don't hesitate to contact me (English or German, both fine). <\/p>\n<h2 id=\"references\">References<\/h2>\n<p>[1] <a href=\"https:\/\/open-cobol.sourceforge.io\/\">https:\/\/open-cobol.sourceforge.io\/<\/a><br\/>\n[2] <a href=\"https:\/\/aur.archlinux.org\/packages\/gnu-cobol\/\">https:\/\/aur.archlinux.org\/packages\/gnu-cobol\/<\/a><br\/>\n[3] <a href=\"http:\/\/deacademic.com\/dic.nsf\/dewiki\/873823\">http:\/\/deacademic.com\/dic.nsf\/dewiki\/873823<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"COBOL"}},{"@attributes":{"term":"Programming"}},{"@attributes":{"term":"Tutorial"}}]},{"title":"Studium: Anrechnung von Studienleistungen \/ Modulen","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/studium\/studium-anrechnung-von-studienleistungen-modulen.html","rel":"alternate"}},"published":"2018-04-15T14:08:00+02:00","updated":"2018-04-15T14:08:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2018-04-15:\/studium\/studium-anrechnung-von-studienleistungen-modulen.html","summary":"<p><em>Disclaimer: Dies ist keine Rechtsberatung und kann eine anwaltliche Beratung nicht ersetzen.<\/em><\/p>\n<p>Beim Wechseln zwischen Studieng&auml;ngen oder Wechseln der Hochschule im Studium stellen sich viele Fragen. Werden meine bereits absolvierten Module angerechnet und welche muss ich erneut besuchen? Werden meine aktuellen Pr&uuml;fungsverfahren terminiert? Was passiert, wenn ich ein Fach entg&uuml;ltig \u2026<\/p>","content":"<p><em>Disclaimer: Dies ist keine Rechtsberatung und kann eine anwaltliche Beratung nicht ersetzen.<\/em><\/p>\n<p>Beim Wechseln zwischen Studieng&auml;ngen oder Wechseln der Hochschule im Studium stellen sich viele Fragen. Werden meine bereits absolvierten Module angerechnet und welche muss ich erneut besuchen? Werden meine aktuellen Pr&uuml;fungsverfahren terminiert? Was passiert, wenn ich ein Fach entg&uuml;ltig nicht bestanden habe?<\/p>\n<p>Eine Pr&uuml;fung ist ein Verfaltungsakt. Der Verwaltungsakt beginnt bei der Anmeldung der Pr&uuml;fung beim ersten Versuch und endet beim bestehen der Pr&uuml;fung, dem entg&uuml;ltig nicht bestehen der Pr&uuml;fung oder beim Abmeldung vom ersten Versuch mit oder ohne trifftigem Grund (an der TU Chemnitz, beachte Fristen). Der Wechsel der Hochschule oder des Studiengangs f&uuml;hrt eigentlich nicht zur Terminierung des Verwaltungsaktes, d.h. wird der Studiengang gewechselt, und steht ein Drittversuch aus, solltet ihr den dennoch nehmen und bestehen, sonst k&ouml;nnte auch das neue Studium in Gefahr sein, wenn das gleiche Modul ebenfalls enthalten ist.<\/p>\n<p>An der TU Chemnitz, sind die entsprechenden Regelungen in der Pr&uuml;fungsordnung verankert. Dort wird erkl&auml;rt, wie das Bestehen und Nicht-Bestehen zu werten ist, wie viele Versuche ihr habt, und wann das Studium endg&uuml;ltig nicht bestanden ist. Die Abschlusspr&uuml;fung oder Bachelor-\/Masterpr&uuml;fung ist an der TU Chemnitz ein virtuelles Konstrukt, was die Gesamtheit des Studienganges umschlie&szlig;t, aber keine eigene Pr&uuml;fung oder kein eigenes Modul darstellt. Die Bachelor- bzw. Masterarbeit ist in modularisierten Studieng&auml;ngen ebenfalls nur ein Modul, die \"Abschlussarbeit\" ebenfalls nur eine Modulpr&uuml;fung wie jede andere auch. Unbeschadet anderer Bedingungen, die die Modulbeschreibung darlegt, k&ouml;nnte das Modul Bachelor- oder Masterarbeit auch das erste Modul sein, was im Studium abgelegt wird.<\/p>\n<p>Wenn ihr Module anrechnen lassen wollt, m&uuml;sst ihr einen Antrag auf Anrechnung von Studienleistungen an den Pr&uuml;fungsausschuss stellen. Der Antrag muss die &uuml;blichen Formalia einhalten, also schriftlich gestellt werden und unterschrieben sein. Gebt die wichtigsten Informationen an, also Studiengang (oder Studieng&auml;nge), Matrikelnummer, Name und kennzeichnet eindeutig, welche Module ihr zu welchen Modulen als gleichwertig betrachtet. Eine Anrechnung von Teilen oder Pr&uuml;fungen w&auml;re auch denkbar.<\/p>\n<p>Nach der Lissabon Konvention [1] m&uuml;ssen die Hochschulen Informationen zur Verf&uuml;gung stellen, welche Kompetenzen in den einzelnen Veranstaltungen \/ Modulen erworben werden. Reicht diese Beschreibungen ebenfalls ein, wenn ihr von einer anderen Hochschule wechselt. Ihr erspart dem Pr&uuml;fungsausschuss damit Arbeit und die M&ouml;glichkeit den Antrag aus formalen Gr&uuml;nden zur&uuml;ckzuweisen.<\/p>\n<p>Eine Qualifikation ist nach Lissabon Konvention dann &auml;quivalent und sollte angerechnet werden, wenn sich die erworbenen Qualifikationen nicht erheblich unterscheiden. Die Universit&auml;t oder genauer der Pr&uuml;fungsausschuss ist dabei in der Beweispflicht, d.h. ihr m&uuml;sst nicht begr&uuml;nden, warum ihr die Module f&uuml;r &auml;quivalent haltet, sondern der Pr&uuml;fungsausschuss muss nachweisen, warum die erworbenen Qualifikationen nicht &auml;quivalent sind. Ihr solltet dazu aber alles N&ouml;tige eingereicht haben.<\/p>\n<p>Die Anrechnung kann auch dann versagt werden, wenn erhebliche Zweifel &uuml;ber das Niveau der Qualifikationen besteht, bspw. wenn die Leistungspunktzahlen sich erheblich unterscheiden. Qualifikationen zu formulieren ist ebenfalls geregelt, es gibt einige verschiedene Richtlinien, bspw. die der Hochschulrektorenkonferenz (HRK) [2].<\/p>\n<h3 id=\"studiengangswechsel-an-der-gleichen-hochschule\">Studiengangswechsel an der gleichen Hochschule<\/h3>\n<p>Ein Wechsel an der gleichen Hochschule ist meist recht einfach. Nicht nur ist der Wechsel an sich einfach, sondern die Anrechnerei geht mehr oder weniger automatisch. Stellt den Antrag, der Pr&uuml;fungsausschuss kann meist recht gut entscheiden, ob die Module gleichwertig sind. Module mit gleichem Namen, Nummer und oder Inhalten \/ Qualifikationszielen sind &auml;quivalent, sollten Unterschiede bestehen, ist das Ermessenssache des Pr&uuml;fungsausschusses.<\/p>\n<h3 id=\"hochschulwechsel\">Hochschulwechsel<\/h3>\n<p>Beim Wechsel an eine andere Hochschule ist etwas mehr Arbeit von N&ouml;ten. Hier solltet ihr die Modulbeschreibungen der fraglichen Module mit einreichen, sodass dem Pr&uuml;fungsausschuss diese Arbeit abgenommen wird. Ein Blick in das entsprechende Hochschulgesetz der Zieluniversit&auml;t kann auch nicht schaden. Die Regelung der Lissabon Konvention findet sich aber in einigen Hochschulgesetzen wieder.<\/p>\n<h3 id=\"drittversuch-und-endgultig-nicht-bestandene-prufungen\">Drittversuch und endg&uuml;ltig nicht bestandene Pr&uuml;fungen<\/h3>\n<p>Wie oben bereits erkl&auml;rt, laufen einmal angefangene Pr&uuml;fungen weiter, bis ihr sie bestanden habt oder endg&uuml;ltig nicht bestanden habt. Eine endg&uuml;ltig nicht bestandene Pr&uuml;fung kann die Studiengangwahl erheblich erschweren. Gebt bei der Bewerbung auf jeden Fall die endg&uuml;ltig nicht bestandenen Pr&uuml;fungen und die laufenden Pr&uuml;fungsverfahren an, wenn ihr danach gefragt werdet. Eine L&uuml;ge hier kann euch die Immatrikulation kosten, auch dann wenn ihr zun&auml;chst angenommen worden seid.<\/p>\n<p>&Uuml;ber die Gleichwertigkeit einer endg&uuml;ltig nicht bestandenen Pr&uuml;fung zu den Pr&uuml;fungen in der fraglichen Studienordnung entscheidet grunds&auml;tzlich der Pr&uuml;fungsausschuss. Auch hier gilt, dass die Gleichwertigkeit dann gegeben ist, wenn kein erheblicher Unterschied in den erworbenen Qualifikationszielen nachgewiesen werden kann. In der Regel sind Pr&uuml;fungsaussch&uuml;sse etwas nachgiebiger bei der Anerkennung von endg&uuml;ltig nicht bestandenen Modulen.<\/p>\n<h3 id=\"beispielantrag\">Beispielantrag<\/h3>\n<p>An der TU Chemnitz gibt es ein Formular f&uuml;r die Anrechnung von Studienleistungen, das muss aber nicht genutzt werden. Zur einfacheren Handhabung ist zu empfehlen die bereitgestellten Formulare zu verwenden, wenn es welche gibt. Ein Antrag kann aber immer auch formlos, schriftlich (mit Unterschrift) gestellt werden.<\/p>\n<p>Der Text sollte dann wenigstens euren Namen, Matrikelnummer, Studieng&auml;nge (und Hochschule) sowie eine Aufstellung enthalten, was f&uuml;r was angerechnet werden soll. Ebenfalls sollte die Note angegeben werden, und Nachweise angeh&auml;ngt sein, bspw. eine Leistungs&uuml;bersicht der Herkunftshochschule. Weiter solltet ihr falls n&ouml;tig die Modulbeschreibungen anh&auml;ngen.<\/p>\n<blockquote>\n<p>Sehr geehrte Frau Prof. X,<\/p>\n<p>Hiermit beantrage ich die Anrechnung der unten stehenden Module. Die Module habe ich an der Hochschule f&uuml;r angewandte Wissenschaften Buxtehude abgelegt. Die erworbenen Kompetenzen der bereits abgelegten Module halte ich f&uuml;r gleichwertig nach dem s&auml;chs. HSFG &sect;35 Abs 9.<\/p>\n<table>\n<thead>\n<tr>\n<th>Bereits abgelegtes Modul<\/th>\n<th>Note<\/th>\n<th>Anzurechnendes Modul<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Angewandte Urlaubswissenschaften<\/td>\n<td>2.3<\/td>\n<td>Entspannung Grundlagen<\/td>\n<\/tr>\n<tr>\n<td>Nasenbohren f&uuml;r Anf&auml;nger<\/td>\n<td>1.3<\/td>\n<td>Ich und mein K&ouml;rper<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Ich habe an der Hochschule f&uuml;r angewandte Wissenschaften Buxtehude 4 Semester den Studiengang Bachelor of Science Urlaubswissenschaften studiert. Aktuell studiere ich den Bachelor of Science Urlaubsplanung (Studienordnungsversion 2017) an der Fachhochschule Sankt Georg in Plauen.<\/p>\n<p>Matrikelnummer: 123456<br\/>\nAnschrift: Stefan Naumann<br\/>\nSankt Georg-Stra&szlig;e 14<br\/>\n08541 Plauen<\/p>\n<p>Mit freundlichen Gr&uuml;&szlig;en,<br\/>\n\\&lt;Unterschrift&gt;<\/p>\n<p>Anlagen:<\/p>\n<ul>\n<li>Leistungs&uuml;bersicht<\/li>\n<li>Modulbeschreibungen von Buxtehude<\/li>\n<li>Modulbeschreibungen von Plauen<\/li>\n<\/ul>\n<\/blockquote>\n<h3 id=\"literatur\">Literatur<\/h3>\n<p>[1] <a href=\"http:\/\/www2.fzs.de\/uploads\/lissabonkonvention.pdf\">Lissabon Konvention<\/a><br\/>\n[2] <a href=\"https:\/\/www.hrk-nexus.de\/fileadmin\/redaktion\/hrk-nexus\/07-Downloads\/07-02-Publikationen\/Kompetenzorientiert-Pruefen.pdf\">HRK Nexus: Kompetenzorientiert Pr&uuml;fern<\/a><\/p>","category":[{"@attributes":{"term":"Studium"}},{"@attributes":{"term":"Anrechnung"}},{"@attributes":{"term":"Lissabon"}},{"@attributes":{"term":"Modul"}},{"@attributes":{"term":"Pr\u00fcfung"}},{"@attributes":{"term":"Pr\u00fcfungsausschuss"}},{"@attributes":{"term":"Studium"}},{"@attributes":{"term":"Verwaltungsrecht"}},{"@attributes":{"term":"VwVfG"}}]},{"title":"MMU on Raspberry Pi (ARMv6 Address Translation)","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/mmu-on-raspberry-pi.html","rel":"alternate"}},"published":"2018-04-02T10:32:00+02:00","updated":"2018-04-02T10:32:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2018-04-02:\/informatik\/mmu-on-raspberry-pi.html","summary":"<h2 id=\"preface\">Preface<\/h2>\n<p>This example demonstrates ARM MMU basics.<\/p>\n<p>You will need the <a href=\"https:\/\/www.scss.tcd.ie\/~waldroj\/3d1\/arm_arm.pdf\">ARM ARM<\/a> (ARM Architectural Reference Manual) for ARMv5.<\/p>\n<p>This code so far does not work on the Raspberry pi 2 yet, will get that working at some point, the knowledge here still applies, I expect the differences to be \u2026<\/p>","content":"<h2 id=\"preface\">Preface<\/h2>\n<p>This example demonstrates ARM MMU basics.<\/p>\n<p>You will need the <a href=\"https:\/\/www.scss.tcd.ie\/~waldroj\/3d1\/arm_arm.pdf\">ARM ARM<\/a> (ARM Architectural Reference Manual) for ARMv5.<\/p>\n<p>This code so far does not work on the Raspberry pi 2 yet, will get that working at some point, the knowledge here still applies, I expect the differences to be subtle between ARMv6 and 7 but will see.<\/p>\n<p>I did not write this text (alone), I merely worked it over. The original can be found on the <a href=\"https:\/\/github.com\/dwelch67\/raspberrypi\/blob\/master\/mmu\/README\">Github-page of David Welch<\/a>, the reworked text on <a href=\"https:\/\/github.com\/naums\/raspberrypi\/blob\/master\/mmu\/README.md\">my Github-page<\/a>.<\/p>\n<h2 id=\"fundamentals\">Fundamentals<\/h2>\n<p>A Memory Managment Unit (MMU) translates virtual addresses into physical addresses, as well as checking access permissions and giving control over marking regions cacheable. This allows the programmer to identify the memory regions which may be cached for faster access in the CPU core, but leaving out for example hardware registers, which are mapped into memory.<\/p>\n<p>There is a boundary inside the chip around the ARM-core. The ARM-core itself uses virtual addresses for memory and hardware-accesses, which are translated by the MMU to physical addresses when actually requesting a value in memory. Every access to the memory or the \"world side\" has to go through the MMU.<\/p>\n<p>When the ARM-core powers up the MMU is disable, which means that every access will pass through unmodified, making the virtual addresses (processor side) equal to the physical addresses (world side). All of the example thus far in this repository (e.g. blinkers) are based in physical addresses.<\/p>\n<p>We already know that somewhere else in the chip the used addresses are different. The Raspberry Pi manual is written for 0x7Exxxxxx based addresses, but for the ARM's physical addresses for the same things is 0x20xxxxxx for the Raspberry Pi 2 and 0x3Fxxxxxx for the Raspberry Pi 2. For this discussion we only care about the ARM and the ARM MMU, not for the other mystical translation on the chip.<\/p>\n<h3 id=\"motivation\">Motivation<\/h3>\n<p>Let's say I am programming a program for let's say Linux. I would have to link my program to use specific addresses (or a specific address space). Let's assume, that our program is loaded into 0x8000 and it can use the memory from 0x0000 onwards. That would be fine for one program, but let's say another program wants to be loaded to 0x8000 or maybe use this space as memory for variables. So how can we run several program without the risk of them clobbering each other?<\/p>\n<p>The answer is neither is actually loaded into 0x8000 when running. The programs may assume, that they can use the addresses like stated above, but in reality the addresses when requesting memory cells will be translated by the MMU. So one program could be placed to 0x10008000, the other one at 0x20008000. When program 1 thinks it accesses 0x0000abcd it is really accessing 0x1000abcd, the other one 0x2000abcd. This translation is completely transparent to the programs, i.e. they will never notice, that the addresses are translated for them.<\/p>\n<p>Theoretically you could assign every virtual address a physical address to be translated to, but that does not make much sense. The ARM-core used on the Raspberry Pi is a 32-bit processor, i.e. it uses 32-bit addresses. This means we have 4 Giga (2\\^32) addresses. A table containing the physical addresses alone would be 16 GB big.<\/p>\n<p>The ARM has one option to translate the top 12 bits of the virtual address to the top 12 bits of the physical address, leaving the lower 20 bits as they are between the virtual and physical space. This means we can control 1 MB of address space per definition and have 4096 entries in a table somewhere to convert virtual to physical addresses. The ARM still uses all 32 Bits, 12 for the top 12 address bits, the other ones as control flags. One of them indicates whether a region is marked as cacheable.<\/p>\n<h3 id=\"about-caching\">About caching<\/h3>\n<p>A cache is a (very small but) very fast memory inside the processor. It is used by the processor transparently to remember data which is loaded and\/or stored by your program together with its address. This behaviour saves the processor from having to request the value from RAM every time it is needed, having to wait for the (slower) memory on every read\/write. Caching can vastly increase the speed of your program. Changes to values are written through the cache.<\/p>\n<p>But why is it disabled with the MMU disabled? Let's assume we want to read the value register of a timer. This is done by reading from a specific address. What we want would be, that we get the current value every time we read the register. When caching is enabled for these memory regions we would read the current value one time, but after that we will only get the cached value. This is no good, because you cannot control peripherals if you are unable to get the current state or value of a peripheral, because the cache only gives you the last (old) values.<\/p>\n<p>Likewise, if you have some RAM, which is shared by more than one resource, like the GPU and the ARM or several processor cores on the Raspberry Pi 2 or 3, you will have a similar situation. In general you want to disable caching on every region which can be modified by other means than through the cache. The MMU let's you enable or disable caching on memory regions.<\/p>\n<h3 id=\"about-access-permissions\">About access permissions<\/h3>\n<p>Let's think back to our example with the two programs running \"at the same time\". You don't want any of the programs to get access to the operating systems data structures nor do you want any of the two modifying code or data of the other program. You would not want a video game to get access to your banking account open in another window, would you? The mechanisms vary by processor family but the MMU provides the security mechanisms. When a particular program is running on the processor there are mean to allow or restrict access to specific memory spaces. If some code accesses an address it does not have the permissions for, then a Data Abort-Exception happens, and the processor will stop running the code of that application. The Operating System will be notified (by the means of an Exception Handler \/ Interrupt Service Routine).<\/p>\n<p>This Data Abort does not have to be fatal for the application, but it could be by design. Think of a virtual machine, running on the processor and when it tries to access its peripherals, the real Operating System can be notified to simulate the peripheral and keep the virtual machine running.<\/p>\n<h3 id=\"about-virtual-memory\">About virtual memory<\/h3>\n<p>What happens when you run out of memory on your computer? Let's say the RAM is use up completely, but an application uses for example <code>malloc<\/code> to request more memory. The operating system will then find a block of memory of another application and save that to disk. This space can then be used by the running application as memory. When the other program then tries to use the swapped out memory, it will trigger an Data Abort-Exception in the processor. This will trigger the operating system to swap that memory block back into memory (maybe substituting another block of another application).<\/p>\n<p>The term swap comes from the idea that these blocks of ram are swapped back and forth to disk, program A's ram goes to disk and is swapped with program T's, then program T's is swapped with program K's and so on. This is why starting right after you venture off that edge from real RAM to virtual, your computers performance drops dramatically and disk activity goes way up. The more things run the more memory needs to be swapped onto the much slower disk.<\/p>\n<h2 id=\"wading-through-the-documentation_1\">Wading through the documentation<\/h2>\n<p>I am mostly using the ARMv5 Architectural Reference Manual DDI0100I. (<a href=\"https:\/\/www.scss.tcd.ie\/~waldroj\/3d1\/arm_arm.pdf\">ARM ARM<\/a>)<\/p>\n<p>Unfortunately the ARM ARM does not look the same from one to the next. With the Raspberry Pi 1 and Zero we are technically using an ARMv6 (architecture version 6), but when we go to ARM's website, there is an ARMv5, ARMv7 and ARMv8-version, but no ARMv6. The ARMv5 manual is actually the original ARM ARM, where they (I assume) realized, that they could not maintain all the architecture variations<br\/>\nin one document forever. So they split them per revision. With respect to the MMU the ARMv5 manual cover the ARMv4, ARMv5 and ARMv6. There is a mode where you can have the same code and table to work on all three, so you don't have to if-then-else your code based on whatever architecture you find. This example is based on this legacy mode with subpages enables.<\/p>\n<p>The 1 MB sections mentioned above are called sections. The ARM MMU also has blobs with a smaller size of 4096 bytes, which are called small page. I will touch on those two sizes.<\/p>\n<p>As mentioned above the Raspberry Pi has a 32 bit address space. 1 MB sections means 20 bits unaltered (bits 32 to 20) and 12 bits translated meaning 4096 1 MB sections, i.e. 4096 entries in the table. The top 12 bits of the virtual address get translated to the top 12 bits of the physical address. There are no additional rules on the translation, you can have for example<\/p>\n<ul>\n<li>virtual = physical<\/li>\n<li>any combination you like<\/li>\n<li>have a bunch of virtual sections point to the same physical space.<\/li>\n<\/ul>\n<p>ARM uses the term Virtual Memory System Architecture or VMSA and they say things like VMSAv6 to talk about the ARMv6 VMSA. There is a section in the ARM ARM titled Virtual Memory System Architecture.<br\/>\nIn there we see the coprocessor registers, specifically CP15 register 2 is the translation table base register. In the CP15 subsection register 2 is the translation table base register. There are three opcodes which give us access to three things: <code>TTBR0<\/code>, <code>TTBR1<\/code> and the control register.<\/p>\n<h3 id=\"writing-the-translation-table-base-address\">Writing the Translation table base address<\/h3>\n<p>First we read this comment (pg. 741, heading: Register 2: Translation table base):<\/p>\n<blockquote>\n<p>If N = 0 always use <code>TTBR0<\/code>. When N = 0 (the reset case), the translation table base is backwards compatible with earlier versions of the architecture.<\/p>\n<\/blockquote>\n<p>So we want to leave N = 0 and use <code>TTBR0<\/code>.<\/p>\n<p>The <code>TTBR0<\/code>-register contains the base address in the physical address space. The bits 31 down to 14-n (with n=0 in our case) are used as the base address. Note that the MMU cannot go through the MMU to figure out how to go through the MMU. It operates exclusively in physical address space and has direct access to memory. In a second we are going to see, that the base address for the MMU table has to be aligned to 16384 bytes (2\\^14), the lower 14 bits of our TLB base address is all zeroes (TLB=Translation Look-Aside Buffer)).<\/p>\n<p>We write that register using<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"nf\">mcr<\/span><span class=\"w\"> <\/span><span class=\"no\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"no\">r0<\/span><span class=\"p\">,<\/span><span class=\"no\">c2<\/span><span class=\"p\">,<\/span><span class=\"no\">c0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"c1\">;@ tlb base<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h4 id=\"the-co-processor\">The co-processor<\/h4>\n<p>Let me explain what that mnemonic does. <code>mcr<\/code> is a special instruction to write to registers of the co-processor. This co-processor manages loads of functions of the ARM-core, like unaligned data access or the MMU. You probably already came across <code>msr<\/code> which is an instruction to store data into the status register of the ARM-core (for example to set a new privilege mode or to enable interrupts). You cannot access the status register or the co-processor registers with the normal <code>mov<\/code> instruction.<\/p>\n<p>The co-processor has several registers, which can be accessed by the <code>mcr<\/code> or the <code>mrc<\/code> instruction. The parameters are:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>MCR{cond} P15,&lt;Opcode_1&gt;,&lt;Rd&gt;,&lt;CRn&gt;,&lt;CRm&gt;,&lt;Opcode_2&gt; <\/code><\/span>\n<span class=\"code-line\">MRC{cond} P15,&lt;Opcode_1&gt;,&lt;Rd&gt;,&lt;CRn&gt;,&lt;CRm&gt;,&lt;Opcode_2&gt;<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch03s02s01.html\">co-processor<\/a> shows the list of registers plus their assignment to the parameters for the two instructions. So the above statement will access the following parameters:<\/p>\n<ul>\n<li>Opcode_1: 0<\/li>\n<li>Rd: r0<\/li>\n<li>CRn: c2 (register number within CP15)<\/li>\n<li>CRm: c0 (operational register)<\/li>\n<li>Opcode_2: 0<\/li>\n<\/ul>\n<p>r0 serves as source register of the value to be written to the Register identified by (c2,c0,0,0).<\/p>\n<h4 id=\"about-tlb\">About TLB<\/h4>\n<p>As far as we are concerned think of the TLB as an array of 32 bit integer, each one being used to translate a virtual to a physical address and describes permissions and caching. My example is going to have a define called <code>MMUTABLEBASE<\/code> which will be where out TLB table starts. The TLB is used as cache for the page tables.<\/p>\n<p>The MMU is completely realised in hardware, but you can configure it the way you want. It will operate on the values we set into our page table with Or and And-operations (i.e. bit-manipulations). It uses portions of the virtual addresses to find the correct plane in the page table to find the according physical address. From the next bits it will decide what to do next. We, as programmers, need to know how the MMU calculates the place, so we can put our descriptor into the correct space, so the MMU finds it.<\/p>\n<h4 id=\"translating-virtual-to-physical-addresses\">Translating virtual to physical addresses<\/h4>\n<p>In the manual there is figure B4-4 (page B4-29), which shows a diagram of how the addresses are translated. It uses X instead of N (which we want to be 0). The modified virtual address in this diagram is, as far as we are concerned, unmodified as we want to intend to use our virtual addresses. The first thing we see, is that the lower 14 Bits of the translation table base (in my example <code>MMUTABLEBASE<\/code>), i.e. the start address of the translation table are marked as SBZ, i.e. should-be-zero. This means, that the translation table should be aligned to 16 KiB (2\\^14 Bytes). Using 0x0000 as starting address would not make much sense, as this is the place for the interrupt vector. The next good place would be 0x00004000. Adding another 16 KiB to that address is (not a coincidence) 0x8000, where we put our code. But any other address, which is aligned to 16 KiB should work, as long as you have enough memory there and not clobber anything else.<\/p>\n<p>The figure B4-4 shows, that we take the top 12 bits of the virtual address, multiply by 4 (or shift left by 2) and add that to the translation table base, which gives the address of the first level descriptor for that virtual address. A multiplication by 4 is no coincidence, but rather takes the length of each descriptor into account (which is exactly 32 bit, or 4 byte). The descriptor is fetched and interpreted. As long as we leave N=0 the MMU will always look into the first 12 bits, which replace the first 12 bits of the virtual address. The last two bits of the descriptor are flags, if they are 0b10, then it is a 1 MB section. If it's something different, then a second level translation will be triggered, but for now let's focus on the simpler part.<\/p>\n<h5 id=\"an-example\">An example<\/h5>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"nx\">MMUTABLEBASE<\/span><span class=\"w\"> <\/span><span class=\"p\">=<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x00004000<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kd\">virtual<\/span><span class=\"w\"> <\/span><span class=\"nx\">address<\/span><span class=\"w\"> <\/span><span class=\"p\">=<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x12345678<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">-<\/span><span class=\"w\">   <\/span><span class=\"nx\">first<\/span><span class=\"w\"> <\/span><span class=\"mi\">12<\/span><span class=\"w\"> <\/span><span class=\"nx\">bit<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"nx\">moved<\/span><span class=\"w\"> <\/span><span class=\"nx\">to<\/span><span class=\"w\"> <\/span><span class=\"nx\">right<\/span><span class=\"p\">):<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x00000123<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">-<\/span><span class=\"w\">   <\/span><span class=\"nx\">multiplied<\/span><span class=\"w\"> <\/span><span class=\"nx\">by<\/span><span class=\"w\"> <\/span><span class=\"mi\">4<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x0000048c<\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">descriptor<\/span><span class=\"w\"> <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"nx\">the<\/span><span class=\"w\"> <\/span><span class=\"nx\">section<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x0000448c<\/span><\/span>\n<span class=\"code-line\"><span class=\"kd\">let<\/span><span class=\"err\">'<\/span><span class=\"nx\">s<\/span><span class=\"w\"> <\/span><span class=\"nx\">assume<\/span><span class=\"w\"> <\/span><span class=\"nx\">the<\/span><span class=\"w\"> <\/span><span class=\"nx\">descriptor<\/span><span class=\"w\"> <\/span><span class=\"nx\">was<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xABC00002<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">-<\/span><span class=\"w\">   <\/span><span class=\"nx\">physical<\/span><span class=\"w\"> <\/span><span class=\"nx\">address<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xABC45678<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h4 id=\"16-mib-supersections_1\">16 MiB Supersections<\/h4>\n<p>So the ARM ARM states, that you can have 16 MiB supersections. This would make life easier, right? Well, no. You still have to generate 16 descriptors for each of the possible 1 MiB sections, so you might as well make them 1 MiB big. You can read up on the differences and try the supersections our, but I'm going to use 1 MiB sections for now.<\/p>\n<p>Maybe you figured out a bit of a problem here. Every load and store with the MMU enabled requires at least one MMU table lookup. The MMU memory accesses of course don't have to go through the MMU, but every other store or load. This does have a performance hit. Therefore the MMU caches the last TLB-lookups. This helps but the conversion has to be done on every requested address.<\/p>\n<h3 id=\"descriptor-format_1\">Descriptor format<\/h3>\n<p>I am looking on the subsection about First Level Descriptors in the ARM ARM, especially the Table B4-1 (pg. B4-27, First-level descriptor format (VMSAv6, subpages enabled)).<\/p>\n<p>This table identifies four different sets of last two bits [1:0]:<\/p>\n<ul>\n<li><code>0b00<\/code> - this section is unmapped. Attempting to access these addresses will generate a translation fault (Data Abort). The bits [31:2] are ignored by the hardware, although it is recommended to keep valid permissions for the descriptor there.<\/li>\n<li><code>0b01<\/code> - for coarse second level table, second level lookup required for translation; allows more fine grained sectioning of the section<\/li>\n<li><code>0b10<\/code> - sections descriptor for its associated virtual addresses, no second level lookup<\/li>\n<li><code>0b11<\/code> - reserved in VMSAv6<\/li>\n<\/ul>\n<p>For now let's work with the <code>0b10<\/code>-entries. The format of the entry is as follows:<\/p>\n<table>\n<thead>\n<tr>\n<th>Bits 31:20<\/th>\n<th>Bits 19:15<\/th>\n<th>14,13,12<\/th>\n<th>11,10<\/th>\n<th>9<\/th>\n<th>8:5<\/th>\n<th>4<\/th>\n<th>3<\/th>\n<th>2<\/th>\n<th>1,0<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Section base address<\/td>\n<td>SBZ<\/td>\n<td>TEX<\/td>\n<td>AP<\/td>\n<td>IMP<\/td>\n<td>Domain<\/td>\n<td>SBZ<\/td>\n<td>C<\/td>\n<td>B<\/td>\n<td><code>10<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The <strong>section base address<\/strong> are the 12 top bits of the physical address, which substitute the top 12 bits of the virtual address. The <strong>C<\/strong> bit marks the address region as cacheable. We do absolute not want to cache peripheral regions, RAM-regions maybe. The C-flag simply asserts bits on the AMDA\/AXI (memory) bus that marks the transaction as cacheable, you still need a cache setup and enabled for the transaction to actually get cached. If you don't have the cache for that transaction type enabled, then it just does a normal memory (or peripheral) operation.<\/p>\n<p>The <strong>B<\/strong> bit, means bufferable, as in write buffer. This enables a \"cache\" but for writing instead of reading. When writing a value to RAM (or peripheral) everything is known, the data and the address. The buffer-bit allows some logic at this level to accept the value and address and continue to write the data to the slower RAM or peripheral (or cache) and let's the CPU go on executing it's<br\/>\nprogram. This may give us a performance boost. When a second write appears and we only have a single place for a transaction, the processor gets stalled until the first one is complete and the second write-command can be saved to the buffer. The advantage is that for a number of writes the processor can hand the needed data to the memory controller and carry on.<\/p>\n<p>You need to look up the <strong>TEX<\/strong> bits yourself. I will stick to them being 0b000 and will not mess with any fancy features here. The combinations of TEX, C and B bits make some subtle differences, look them up in Table B4-3 (CB + TEX Encodings).<\/p>\n<p>The <strong>AP<\/strong> bits indicate the level of access permissions (see Table B4-1 MMU access permissions, pg. B4-9), for page table formats, which don't support APX, value 0 is assumed. The following AP-values are therefore valid:<\/p>\n<ul>\n<li><code>0b00<\/code> - No access for anyone; will generate permission fault on every access<\/li>\n<li><code>0b01<\/code> - Read\/Write permission for privileged mode<\/li>\n<li><code>0b10<\/code> - Read\/write for privileged mode, read for user mode (writes in user mode trigger permission faults)<\/li>\n<li><code>0b11<\/code> - Full access (R\/W for everyone)<\/li>\n<\/ul>\n<p>The <strong>domain<\/strong> is a bit trickier to explain. There is a register right next to the translation table base address register which contains 16 different domain specifications. These definitions are 2 bit long each:<\/p>\n<ul>\n<li><code>0b00<\/code> - <strong>no access<\/strong>, any access generates a domain fault<\/li>\n<li><code>0b01<\/code> - <strong>client<\/strong>, accesses are checked against the access permission bits in the TLB entry<\/li>\n<li><code>0b10<\/code> - <strong>UNPREDICTABLE<\/strong> behaviour<\/li>\n<li><code>0b11<\/code> - <strong>manager<\/strong>, accesses are not checked and cannot generate a permission fault<\/li>\n<\/ul>\n<p>The domains basically are 16 different definitions which control the behaviour on access. We can define for example 16 types of applications and assign them sections. We assign sections to domains by setting the four <strong>domain<\/strong> bits of the translation table entry to the number of the definition in the register. With changing to bits in this register we can then put sections of a domain into another permission mode, which is quite useful, because we don't need to change the MMU table.<\/p>\n<p>For starters we are going to set all of the domains to <code>0b11<\/code> don't check and all of our sections can have the domain number 0.<\/p>\n<h2 id=\"a-simple-implementation_1\">A simple implementation<\/h2>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cm\">\/**<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief creates an translation table entry (for sections of size 1 MiB)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param[in] virtual the virtual address (only top 12 bits used)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param[in] physical the physical address (only top 12 bits used)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param[in] flags the flags for the section<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">**\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"nf\">mmu_section<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">virtual<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">physical<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">flags<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">offset<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">virtual<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;&gt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">20<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">entry<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">MMUTABLEBASE<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">offset<\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"mi\">2<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ mask lower 20 bits of physical address then ORR flags and 0x02 for 1 MiB<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">physval<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">physical<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xfff00000<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">flags<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x7ffc<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x02<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"o\">*<\/span><span class=\"n\">entry<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">physval<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define CACHEABLE 0x08<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define BUFFERABLE 0x04<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"filling-the-table-with-sections\">Filling the table with sections<\/h3>\n<p>Before enabling the MMU itself we need to make sure, that every section of memory we want to use is defined with a valid entry in the table. If not, access to that region will trigger a fault handler - if you decide to write one. Which in turn can access to non mapped memory - which is not good.<\/p>\n<p>The smallest amount of RAM on a Raspberry Pi is 256 MiB or 0x10000000 bytes. Our program enters at address 0x8000, so that is within the first section 0x000xxxxx so we should make that section cacheable and bufferable.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x00000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00000000<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">CACHEABLE<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">BUFFERABLE<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This statement will create an entry for the virtual address space 0x000xxxxx to the physical addresses 0x000xxxxx enable the cache and write buffer. If we want to use all 256mb we would need to do this for all the sections from 0x000xxxxx to 0x100xxxxx.<\/p>\n<p>We know that for the Raspberry Pi 1 the peripherals, like AUX \/ UART and such are in ARM physical space at 0x20xxxxxx. To allow for more RAM on the Raspberry Pi 2 they needed to that peripheral base address and moved it to 0x3Fxxxxxx. We can either create 16 1 MiB section entries to cover the whole range of peripherals or we only define the sections we care to talk to. The UART and the GPIO are associated with the 0x202xxxxx space. There are a couple of timers in the 0x200xxxxx space so one entry can cover those.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x20000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x20000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/NOT CACHED! <\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x20200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x20200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/NOT CACHED! <\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x3F000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x3F000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/NOT CACHED! <\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x3F200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x3F200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/NOT CACHED!<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>These sections are not cached and not buffered, but but we may play with that to demonstrate what caching a peripheral can do to you, why we need to turn on the MMU if for no other reason than to get some bare metal performance by using the cache.<\/p>\n<p>Now you have to think on a system level here, there are a number of things in play. We need to plan our memory space, where are we putting the MMU table, where are our peripherals, where is our program.<\/p>\n<p>If the only reason for using the MMU is to allow the use of the cache then just map the whole world 1:1; if you want with the peripherals not cached and the rest cached.<\/p>\n<h3 id=\"cache-invalidation\">Cache invalidation<\/h3>\n<p>So once our tables are setup then we need to actually turn the MMU on. When initialising a cache to you want to clean out all the entries in a safe way. You want to invalidate everyhting, mark every cache line as empty \/ available. Likewise you want the TLB caching the MU does to be invalidated, so the MMU starts up with no valid lines in the cache, that don't match our entries. Also we want the CPU to do a Data Synchronization Barrier (DSB), so every explicit memory transaction is finished before the next instruction begins.<\/p>\n<p>All of the above can be done using the C15 <a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch03s02s01.html\">co-processor<\/a>. So, to summarise:<\/p>\n<ol>\n<li>Invalidate all caches (Instruction and data, write 0 to <code>0, c7, c7, 0<\/code>)<\/li>\n<li>Invalidate the TLB entries (write 0 to <code>0, c8, c7, 0<\/code>)<\/li>\n<li>Data synchronisation barrier (write 0 to <code>0, c7, c10, 4<\/code>)<\/li>\n<li>Set the domain access controls (write 0xffffffff to <code>0, c3, c0, 0<\/code>, 0b11 for every domain)<\/li>\n<li>Set the base address for the translation table (<code>0,c2,c0,0<\/code>)<\/li>\n<li>Enable level 1 caches and the MMU in the control register (<code>0,c1,c0,0<\/code>) and some other useful things:<ul>\n<li>bit 0 (M) enables MMU<\/li>\n<li>bit 2 (C) enables level 1 data cache<\/li>\n<li>bit 11 (Z) enables branch prediction<\/li>\n<li>bit 12 (I) enables instruction cache<\/li>\n<li>bit 22 (U) enables non-aligned data access as well as mixed big-\/little-endian data access<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>What bits of these you want to set is up to you. I would recommend M, C and I, but I am going ahead and set them all. So simple example code implementing the the MMU-enabling process might be this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"p\">.<\/span><span class=\"n\">global<\/span><span class=\"w\"> <\/span><span class=\"n\">mmu_init<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nl\">mmu_init<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"err\">#<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ invalidate caches<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">c7<\/span><span class=\"p\">,<\/span><span class=\"n\">c7<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ invalidate TLB entries<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">c8<\/span><span class=\"p\">,<\/span><span class=\"n\">c7<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ data synchronisation barrier<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">c7<\/span><span class=\"p\">,<\/span><span class=\"n\">c10<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ set all domains to 0b11<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mh\">0xffffffff<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">c3<\/span><span class=\"p\">,<\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ set the translation table base address (remember to align 16 KiB!)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"n\">c2<\/span><span class=\"p\">,<\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ set the bits mentioned above<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mh\">0x00401805<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mrc<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">orr<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>For messing with the translation tables after the MMU is started, you will need to invalidate the TLB cache again, so let's put this part into its own function. We don't need to care about the L1 cache, this time. Also ARMv6 introduces a feature to help with invlidating the TLB, but I'm going with this solution:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">tlb_invalidate<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nl\">tlb_invalidate<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"err\">#<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ invalidate TLB entries<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">c8<\/span><span class=\"p\">,<\/span><span class=\"n\">c7<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ data synchronisation barrier<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"n\">c7<\/span><span class=\"p\">,<\/span><span class=\"n\">c10<\/span><span class=\"p\">,<\/span><span class=\"mi\">4<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h4 id=\"-jtag-debugging-and-caching\">(JTAG) Debugging and caching<\/h4>\n<p>Something to note here. Debugging using the JTAG based on-chip-debugger makes life easier. No SD-card swapping and no more EEPROM-flashing. BUT, it is not completely without issue. The basic problem is that caches often seperate instruction fetches from data reads and writes. Let's say you execute instructions at 0xD0000 (which is cached) and an instruction 0xC000. So you transfer your programm, set the start address and run again.<\/p>\n<p>For each instruction in the program the prior instruction in that address might still be in the instruction cache and the new one in main RAM (or data cache). So, when running the new program you might still be running the old instructions, which are fetched back from the instruction cache, not the RAM, unless an invalidate or flush happens).<\/p>\n<p>There is also the question of are the instruction and data caches shared? They can be specific to the core and your setup. Is your JTAG-debugger able to disable the caches, has it done that for you, or can you do it manually.<\/p>\n<p>Any time you are using the instruction or data caches you need to be careful using a JTAG-debugger or even a bootloader type approach depending on its design as you might end up doing data writes of instructions and going around the instruction cache or worse. This may be done by your JTAG debugger, but keep in mind to change back to \/ from Raspberry Pi 2 when switching between the Pis. Otherwise this might driver you mad, when you keep downloading new code but the Pi crashes or behaves unexpectedly.<\/p>\n<h2 id=\"having-fun-with-address-translation_2\">Having fun with address translation<\/h2>\n<p>So the example is going to start with the MMU off and write to addresses in four different 1MB address spaces, so we can play with the section descriptors and demonstrate virtual to physical address conversion later.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ write data to four different 1 MiB sections<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">PUT32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00045678<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00045678<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">PUT32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00145678<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00145678<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">PUT32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00245678<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00245678<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">PUT32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00345678<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00345678<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ write the data back to UART<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00045678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00145678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00245678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00345678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ 0D    CR  '\\r' (carriage ret)<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0D<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ 0A    LF  '\\n' (new line)<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0A<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ Then setup the MMU with at least those four sections<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00000000<\/span><span class=\"p\">,<\/span><span class=\"n\">CACHEABLE<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"n\">BUFFERABLE<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00100000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00100000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00300000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00300000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/  and the peripherals:<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x20000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x20000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/NOT CACHED!<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x20200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x20200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/NOT CACHED!<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ Start the MMU with the instruction and data caches enabled:<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_init<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">MMUTABLEBASE<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ when we read those four addresses back we get the same output<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ as we wrote before because we mapped virtual = physical<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00045678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00145678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00245678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00345678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0D<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0A<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>But what if we swizzle things around? Don't mess with the 0x00000000-section, because that is where our code is.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ change the table entries<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00100000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00300000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00200000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00000000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00300000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00100000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ invalidate the TLB<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">invalidate_tlbs<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ and read the addresses again, which we wrote to above<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00045678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00145678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00245678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00345678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0D<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0A<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The 0x000xxxxx entry was not modified, so we get 0x000045678 as the output. The section 0x001xxxxx will read from physical addresses 0x003xxxxx so we get the 0x00345678 output, 0x002xxxxx will translate to the 0x000xxxxx space so that read gives 0x00045678 and the 0x003xxxxx is mapped to physical 0x001xxxxx giving 0x00145678 as the output.<\/p>\n<p>So up to this point the output looks like this:<\/p>\n<blockquote>\n<p>00045678<br\/>\n00145678<br\/>\n00245678<br\/>\n00345678<\/p>\n<p>00045678<br\/>\n00145678<br\/>\n00245678<br\/>\n00345678<\/p>\n<p>00045678<br\/>\n00345678<br\/>\n00045678<br\/>\n00145678<\/p>\n<\/blockquote>\n<p>The first block is with the MMU disabled, the second one with MMU enabled but 1:1 virtual to physical translation, the third one with the non 1:1 translation.<\/p>\n<h2 id=\"coarse-paging\">Coarse paging<\/h2>\n<p>With coarse paging the logic does not know what kind of translation will be done until the first level read, so the first step is identical to the translation above. If it sees a <code>0b01<\/code> as the lower 2 bits of the first level descriptor, then it knows, it's a coarse page entry and it needs as second level fetch. Table B4-5 Accessing coarse page table second-level descriptors (pg. B4-30) shows the logic fetching the second level descriptor.<\/p>\n<h3 id=\"second-level-descriptor-format\">Second level descriptor format<\/h3>\n<p>There are two things to the two level translation. At first we need to set the first level descriptors accordingly. The format is as follows Table B4-1 (pg. B4-27, First-level descriptor format (VMSAv6, subpages enabled)).<\/p>\n<table>\n<thead>\n<tr>\n<th>Bits 31:10<\/th>\n<th>9<\/th>\n<th>8:5<\/th>\n<th>4,3,2<\/th>\n<th>1,0<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Coarse Page Table base Address<\/td>\n<td>IMP<\/td>\n<td>Domain<\/td>\n<td>IMP<\/td>\n<td><code>01<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The bits 4:2 are implementation defined and should be zero (SBZ) for VMSAv6. The domain-bits are used as above. The bits 31:10 are used as the base address of the second level page table. This second level page table needs to be aligned to 1 KiB in memory.<\/p>\n<p>So after fetching the first level descriptor the bits 31:10 of the entry will be used as bits 31:10 of the second level descriptor, i.e. it will be used as base address for the second level table. The virtual address bits 19:12 will be used to navigate inside that second level table, i.e. shift completely to the right, multiplied by 4 then used added onto the base address. The lowest 2 bits of the address of the second level entry is always zero. Note that there are 256 possibilities to fill the bits 19:12 of the virtual address, i.e. the section is divided into 256 parts, i.e. 4 KiB pages.<\/p>\n<p>The second level descriptor looks like this (for small pages, for more see Table 4-3 Second level descriptor format (subpages enabled), pg. 4-31):<\/p>\n<table>\n<thead>\n<tr>\n<th>Bits 31:12<\/th>\n<th>11,10<\/th>\n<th>9,8<\/th>\n<th>7,6<\/th>\n<th>5,4<\/th>\n<th>3<\/th>\n<th>2<\/th>\n<th>1,0<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Small page base address<\/td>\n<td>AP3<\/td>\n<td>AP2<\/td>\n<td>AP1<\/td>\n<td>AP0<\/td>\n<td>C<\/td>\n<td>B<\/td>\n<td><code>10<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Note, that there are four <strong>AP<\/strong>-fields here. The small page is divided further into four blocks of the same size (i.e. in the case of small pages 1 KiB), which have their own AP-Access control. AP0 applies to the block with the lowest base address. You can set them all to <code>0b11<\/code> - full access and not care, or have fine grained access control over the blocks of that page.<\/p>\n<h3 id=\"an-example_1\">An example<\/h3>\n<p>This example is a bit crazy, as the address of the second level descriptor is an address, where we don't even have RAM anymore on the Raspberry Pi. Normally you want to keep your second level tables somewhere near the first level table, so you have the memory managment information in a confined space.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"nx\">MMUTABLEBASE<\/span><span class=\"w\"> <\/span><span class=\"p\">=<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x00004000<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kd\">virtual<\/span><span class=\"w\"> <\/span><span class=\"nx\">address<\/span><span class=\"w\"> <\/span><span class=\"p\">=<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x12345678<\/span><\/span>\n<span class=\"code-line\"><span class=\"o\">-<\/span><span class=\"w\">   <\/span><span class=\"nx\">bits<\/span><span class=\"w\"> <\/span><span class=\"mi\">19<\/span><span class=\"p\">:<\/span><span class=\"mi\">12<\/span><span class=\"w\"> <\/span><span class=\"nx\">of<\/span><span class=\"w\"> <\/span><span class=\"nx\">the<\/span><span class=\"w\"> <\/span><span class=\"kd\">virtual<\/span><span class=\"w\"> <\/span><span class=\"nx\">address<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x00000045<\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">address<\/span><span class=\"w\"> <\/span><span class=\"nx\">of<\/span><span class=\"w\"> <\/span><span class=\"nx\">the<\/span><span class=\"w\"> <\/span><span class=\"nx\">first<\/span><span class=\"w\"> <\/span><span class=\"nx\">level<\/span><span class=\"w\"> <\/span><span class=\"nx\">descriptor<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x0000448c<\/span><\/span>\n<span class=\"code-line\"><span class=\"kd\">let<\/span><span class=\"err\">'<\/span><span class=\"nx\">s<\/span><span class=\"w\"> <\/span><span class=\"nx\">assume<\/span><span class=\"w\"> <\/span><span class=\"nx\">a<\/span><span class=\"w\"> <\/span><span class=\"nx\">descriptor<\/span><span class=\"w\"> <\/span><span class=\"nx\">value<\/span><span class=\"w\"> <\/span><span class=\"nx\">of<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xABCDE001<\/span><\/span>\n<span class=\"code-line\"><span class=\"kd\">base<\/span><span class=\"w\"> <\/span><span class=\"nx\">address<\/span><span class=\"w\"> <\/span><span class=\"nx\">of<\/span><span class=\"w\"> <\/span><span class=\"nx\">second<\/span><span class=\"w\"> <\/span><span class=\"nx\">level<\/span><span class=\"w\"> <\/span><span class=\"nx\">table<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xABCDE000<\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">offset<\/span><span class=\"w\"> <\/span><span class=\"nx\">to<\/span><span class=\"w\"> <\/span><span class=\"nx\">the<\/span><span class=\"w\"> <\/span><span class=\"nx\">second<\/span><span class=\"w\"> <\/span><span class=\"nx\">level<\/span><span class=\"w\"> <\/span><span class=\"nx\">table<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x00000114<\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">address<\/span><span class=\"w\"> <\/span><span class=\"nx\">of<\/span><span class=\"w\"> <\/span><span class=\"nx\">the<\/span><span class=\"w\"> <\/span><span class=\"nx\">second<\/span><span class=\"w\"> <\/span><span class=\"nx\">level<\/span><span class=\"w\"> <\/span><span class=\"nx\">descriptor<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xABCDE114<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"a-simple-implementation_2\">A simple implementation<\/h3>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cm\">\/**<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief creates an translation table entry (for sections of size 1 MiB)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param[in] virtual the virtual address (only top 12 bits used)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param[in] physical the physical address (only top 12 bits used)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param[in] flags the flags for the section<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"nf\">mmu_page<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">virtual<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">physical<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">flags<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">secondbase<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">offset<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">virtual<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;&gt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">20<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ plus and or are the same thing here, as MMUTABLEBASE is 14 bit aligned<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">entry<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">MMUTABLEBASE<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">offset<\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"mi\">2<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ mask lower 20 bits of physical address then ORR flags and 0x01 for coarse translation<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">entryval<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">secondbase<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xfffffc00<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">flags<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xf0<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x01<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ set first level descriptor<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"o\">*<\/span><span class=\"n\">entry<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">entryval<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ mask everything except bits 19:12<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">offset<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">virtual<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;&gt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">12<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xff<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ form the second level<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">secondLevelEntry<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">secondbase<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xfffffc00<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">offset<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">2<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ form the value of the second level descriptor<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ bytes 31:12 are the page base address, flags contain B,C, AP_x = 0b11 <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ for all and the 0x02 at the end to identify the entry as small page<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">physval<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">physical<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xfffff000<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xff0<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">flags<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xc<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x02<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ set the second level descriptor<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"o\">*<\/span><span class=\"n\">secondLevelEntry<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">physval<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>So let's assign some sections to coarse translation:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">mmu_small<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0AA45000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00145000<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00000400<\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_small<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0BB45000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00245000<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00000800<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_small<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0CC45000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00345000<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00000C00<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_small<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0DD45000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00345000<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00001000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_small<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0DD46000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00146000<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00001000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">invalidate_tlb<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Let's look in the last two <code>mmu_small<\/code>-statements here. you will notice, that the <code>secondbase<\/code>-parameter is the same here. This is in fact wanted, as I want to add an entry into the secondary table I assigned before, not set a new one, i.e. orphaning the old one. So let's assume I would set a new secondary table base address like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">mmu_small<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0DD45000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00345000<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00001000<\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_small<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0DD46000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00146000<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00001400<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>When I try to access an address in the page 0x0DD45xxx, then the MMU would look inside a secondary table located at 0x00001400, which of course does not contain our previously set entry for the small page. But it will definitely find something there, and probably behave unexpected, if we are not aware of our mistake here. So always make sure the secondary table base addresses of the pages in the same section are the same.<\/p>\n<h2 id=\"access-violation_1\">Access violation<\/h2>\n<p>First we want to set a domain to 0x00, so accessing a section with that domain will definitely trigger an access violation. I will assume we wrote that to domain number 1.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ set the domain of a section to 0x01<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mmu_section<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00100000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x00100000<\/span><span class=\"p\">,<\/span><span class=\"mh\">0x0020<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">invalidate_tlb<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ then read the data from the sections<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00045678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00145678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00245678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">hexstring<\/span><span class=\"p\">(<\/span><span class=\"n\">GET32<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x00345678<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0D<\/span><span class=\"p\">);<\/span><span class=\"w\"> <\/span><span class=\"n\">uart_send<\/span><span class=\"p\">(<\/span><span class=\"mh\">0x0A<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>I expect that second read-statement to trigger a Data Abort-Exception, so I want to write an exception handler, to read the status information of that exception. We need to following registers of the C15 co-processor:<\/p>\n<ul>\n<li><code>0,c5,c0,0<\/code> - Data Fault Status Register<\/li>\n<li><code>0,c5,c0,1<\/code> - Instruction Fault Status Register<\/li>\n<\/ul>\n<h3 id=\"data-fault-status-register\">Data Fault Status Register<\/h3>\n<p>This register holds the source of the last data fault. The bits have the following functions:<\/p>\n<table>\n<thead>\n<tr>\n<th>Bit 31:13<\/th>\n<th>12<\/th>\n<th>11<\/th>\n<th>10<\/th>\n<th>9<\/th>\n<th>8<\/th>\n<th>7:4<\/th>\n<th>3:0<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>SBZ<\/td>\n<td>SD<\/td>\n<td>RW<\/td>\n<td>S<\/td>\n<td>0<\/td>\n<td>0<\/td>\n<td>Domain<\/td>\n<td>Status<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>SD<\/strong> indicates an AXI Decode or Slave error caused the abort (only valid for external aborts, for all other should be zero). <strong>RW<\/strong> indicates whether a read (0) or a write (1) access caused the abort. The <strong>S<\/strong>-flag is part of the status field. The <strong>Domain<\/strong> bits indicate the domain which was accessed when the abort occurred. The <strong>Status<\/strong> bits show the type of fault generated. See the <a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/Bgbiaghh.html\">Data Fault Status Register<\/a>-manual for a list.<\/p>\n<h3 id=\"instruction-fault-status-register\">Instruction Fault Status Register<\/h3>\n<p>This register holds the source of the last instruction fault. The bits have the following functions:<\/p>\n<table>\n<thead>\n<tr>\n<th>Bit 31:13<\/th>\n<th>12<\/th>\n<th>11<\/th>\n<th>10<\/th>\n<th>9:4<\/th>\n<th>3:0<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>SBZ<\/td>\n<td>SD<\/td>\n<td>SBZ<\/td>\n<td>0<\/td>\n<td>SBZ<\/td>\n<td>Status<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>See the <a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/Bgbccfgi.html\">Instruction Fault Status Register<\/a>-manual for the list of status combinations.<\/p>\n<h3 id=\"reading-the-status-registers\">Reading the status registers<\/h3>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"nl\">data_abort<\/span><span class=\"p\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ save the link-register<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ get the last executed instruction<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,[<\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"err\">#<\/span><span class=\"mi\">-8<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ reading the status register<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mrc<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"n\">c5<\/span><span class=\"p\">,<\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">;<\/span><span class=\"err\">@<\/span><span class=\"w\"> <\/span><span class=\"n\">data<\/span><span class=\"o\">\/<\/span><span class=\"n\">combined<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mrc<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"n\">c5<\/span><span class=\"p\">,<\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">;<\/span><span class=\"err\">@<\/span><span class=\"w\"> <\/span><span class=\"n\">instruction<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">sp<\/span><span class=\"p\">,<\/span><span class=\"err\">#<\/span><span class=\"mh\">0x00004000<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ print data fault status register<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"n\">r4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">hexstring<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ print instruction fault status register<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"n\">r5<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">hexstring<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ print the link register<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"n\">r6<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">hexstring<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ print the bit-representation of the last executed instruction<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"n\">r8<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">hexstring<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">b<\/span><span class=\"w\"> <\/span><span class=\"n\">hang<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Running the code results in:<\/p>\n<blockquote>\n<p>00045678<br\/>\n00000019<br\/>\n00000000<br\/>\n00008104<br\/>\nE5900000<\/p>\n<\/blockquote>\n<p>The first line is the one correct data-read we do in our code above. The next value is the data fault status register, which indicates that the domain 0x01 was accessed and aborted with an 0x09 fault, i.e. a Domain Section fault. The third line is the value of the instruction fault status register, which indicates a status of 0x0, i.e. \"no function, reset value\". That probably means no fault happened.<\/p>\n<p>The fourth line is the link register, i.e. the address to the instruction which would have been executed next, and the last line is the binary representation of the instruction which caused the fault. Use a disassembler to view the instruction in all its mnemonic glory:<\/p>\n<blockquote>\n<p>80fc: e5900000 ldr r0, [r0]<\/p>\n<\/blockquote>\n<h1>Conclusion<\/h1>\n<p>This is just a simple intro to MMUs, just enough to be dangerous. The MMU is one of the simplest peripherals to program so long as bit manipulations are not something that causes you to lose sleep. But if you mess it up even a bit, or forget something, you can crash in spectacular ways (often silently without any way of knowing what really happened. Debugging can be hard at best.<\/p>\n<p>The ARM ARM indicates that ARMv6 adds a feature of separating the data from the instructions from the MMUs perspective, which is an interesting thought (see the JTAG-debugging comments).<\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Address"}},{"@attributes":{"term":"ARM"}},{"@attributes":{"term":"ARMv6"}},{"@attributes":{"term":"Memory"}},{"@attributes":{"term":"MMU"}},{"@attributes":{"term":"Physical Address"}},{"@attributes":{"term":"Raspberry Pi"}},{"@attributes":{"term":"Translation"}},{"@attributes":{"term":"Virtual Address"}}]},{"title":"Studium: Anfechtung einer Pr\u00fcfung \/ Pr\u00fcfungsergebnis","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/studium\/studium-anfechtung-einer-pruefung-pruefungsergebnis.html","rel":"alternate"}},"published":"2018-03-13T11:38:00+01:00","updated":"2018-03-13T11:38:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2018-03-13:\/studium\/studium-anfechtung-einer-pruefung-pruefungsergebnis.html","summary":"<p><em>Disclaimer: Dies ist keine Rechtsberatung. Wenn du den Drittversuch nicht bestanden hast, solltest du dir lieber einen Anwalt suchen, der kann dich besser beraten und vertreten.<\/em><\/p>\n<p>Jeder Student kennt das. Im Laufe des Studiums geht mal eine Pr&uuml;fung daneben, das kann hei&szlig;en, dass man selbst nicht ausreichend darauf vorbereitet ist \u2026<\/p>","content":"<p><em>Disclaimer: Dies ist keine Rechtsberatung. Wenn du den Drittversuch nicht bestanden hast, solltest du dir lieber einen Anwalt suchen, der kann dich besser beraten und vertreten.<\/em><\/p>\n<p>Jeder Student kennt das. Im Laufe des Studiums geht mal eine Pr&uuml;fung daneben, das kann hei&szlig;en, dass man selbst nicht ausreichend darauf vorbereitet ist, aber auch, dass die Pr&uuml;fung nicht ordnungsgem&auml;&szlig; abgelaufen ist. Das Ergebnis kann ganz verschieden sein, muss aber auch noch nicht mal feststehen, aber man bleibt der Ansicht, dass hier etwas komisches passiert ist.<\/p>\n<p>Ganz wichtig ist, dass der Studierende die Pflicht hat mitzuwirken. D.h. sie muss Missst&auml;nde anzeigen, idealerweise bereits der Aufsicht in schriftlichen Pr&uuml;fungen oder dem Pr&uuml;fer in m&uuml;ndlichen. Die Aufsicht hat dann die M&ouml;glichkeit den Missstand aus der Welt zu schaffen, bspw. indem sie von sich aus eine Schreibzeitverl&auml;ngerung gibt, oder Fenster verschlie&szlig;t (bspw. bei Baul&auml;rm vor dem Pr&uuml;fungsraum).<\/p>\n<p>Der Mangel wurde aber nicht g&auml;nzlich beseitigt und so ganz wird man das Gef&uuml;hl nicht los, dass das Pr&uuml;fungsverfahren mangelhaft ist. Jetzt sollte ein Antrag an den Pr&uuml;fungsausschuss geschrieben werden. Zum Einen gilt auch nach der Pr&uuml;fung noch die Mitwirkungspflicht, manche Pr&uuml;fungsaussch&uuml;sse stellen sich bspw. quer, wenn die Ergebnisse bereits ver&ouml;ffentlicht sind.<\/p>\n<p>Ein Antrag im <strong>Verwaltungsrecht<\/strong> (eine Universit&auml;t f&auml;llt da rein) ist grunds&auml;tzlich formlos m&ouml;glich. Auch wenn die Universit&auml;t Formulare anbieten sollte, kann ein Antrag theoretisch auf einem St&uuml;ck Toilettenpapier gestellt werden. Ich empfehle euch allerdings einen Brief aufzusetzen, in dem ihr neben Kontaktinformationen, Matrikelnummer, Studiengang und Studienordnungsversion, euer Anliegen klar formuliert und idealerweise eine Begr&uuml;ndung oder eine Beschreibung eurer Sicht formuliert. Die Amtssprache ist Deutsch (&sect;23 Abs. 1).<\/p>\n<p>Das Pr&uuml;fungsverfahren ist im Gesamten ein Verwaltungsakt. Gegen einen Verwaltungsakt (bzw. genauer gegen das Ergebnis eines Verwaltungsakt) kann man \"klagen\" (hier erstmal au&szlig;ergerichtlich). Der Verwaltungsakt beginnt mit der Anmeldung zur Pr&uuml;fung, und endet mit dem Bestehen der Pr&uuml;fung oder dem entg&uuml;ltig nicht Bestehen der Pr&uuml;fung. Manche Universit&auml;ten erlauben den R&uuml;cktritt von einer Pr&uuml;fung vorher (bspw. bis 7 Tagen vor dem Termin ohne Grund, danach mit trifftigem Grund), und beenden daraufhin den Verwaltungsakt, wenn ihr nicht durchgefallen seid. Also ihr meldet euch zum ersten Mal zur Pr&uuml;fung an, meldet euch vorher wieder ab (entweder mit oder ohne Grund gem&auml;&szlig; den Fristen aus der Studienordnung), dann z&auml;hlt das als h&auml;ttet ihr euch nie angemeldet.<\/p>\n<p>Der Bescheid &uuml;ber das Nicht-Bestehen einer Pr&uuml;fung enth&auml;lt grunds&auml;tzlich eine Rechtsbehelfsbelehrung. Die ist daf&uuml;r da euch darauf hinzuweisen, dass ihr gegen den Bescheid widersprechen k&ouml;nnt, bspw. wenn ihr neue Informationen habt oder glaubt zu Unrecht durch die Pr&uuml;fung durchgefallen zu sein.<\/p>\n<h3 id=\"krankheit\">Krankheit<\/h3>\n<p>Ein wichtiger Grund ist die Krankheit bei einer Pr&uuml;fung. Seht ihr euch nicht in der Lage zu einer Pr&uuml;fung anzutreten, weil ihr krank seid, m&uuml;sst ihr einen Arzt aufsuchen und meist von ihr ein Formular ausf&uuml;llen lassen, was von der Universit&auml;t gestellt wird. Manche Universit&auml;ten erlauben aber auch die Einreichung von Arbeitsunf&auml;higkeitsbescheinigungen. Die gestellten Formulare enthalten zu meist Informationen &uuml;ber euren Gesundheitszustand, datenschutzrechtliche Debatten solltet ihr aber nicht f&uuml;hren, wenn ihr wegen Krankheit von einer Pr&uuml;fung zur&uuml;cktreten wollt.<\/p>\n<p>Das Formular muss zusammen mit einem Antrag auf R&uuml;cktritt von der Pr&uuml;fung unverz&uuml;glich an das zust&auml;ndige Pr&uuml;fungsamt. Unverz&uuml;glich hei&szlig;t dabei aber nicht \"innerhalb von 3 Tagen\", sondern ohne schuldhaftes Verz&ouml;gern. Solltet ihr euch bspw. ein Bein gebrochen haben oder im Krankenhaus liegen, reicht das Einreichen auch dann, wenn ihr gesundheitlich wieder in der Lage dazu seid. Alternativ k&ouml;nnt ihr den Antrag auch per Post verschicken. Vorrang w&auml;hrend ihr krank seid hat allerdings, dass ihr wieder gesund werdet.<\/p>\n<p>Ihr k&ouml;nnt auch w&auml;hrend einer Pr&uuml;fung von der Pr&uuml;fung zur&uuml;cktreten, bspw. weil ihr erst mit leichten Kopfschmerzen gekommen seid, und dann merkt, dass die Kopfschmerzen schlimmer werden und ihr euch nicht (mehr) konzentrieren k&ouml;nnt. Solltet ihr das merken, sagt <strong>sp&auml;testens<\/strong> zur Abgabe der Klausur der Aufsicht bescheid und geht unverz&uuml;glich zum Arzt um den obigen Antrag am Pr&uuml;fungsamt zu stellen.<\/p>\n<h3 id=\"beschwerde-nach-der-prufung\">Beschwerde nach der Pr&uuml;fung<\/h3>\n<p>Man kann sich aus vielerlei Gr&uuml;nden nach der Pr&uuml;fung beschweren. Neben der Befangenheit der Pr&uuml;fer oder der Pr&uuml;ferbestellung auch &uuml;ber Aufgaben oder den Ablauf der Pr&uuml;fung. Werden beispielsweise wichtige Information nur an die Tafel geschrieben, ohne explizit darauf hinzuweisen, k&ouml;nnte darin ein Widerspruchsgrund liegen. Interessant wird es auch dann, wenn einige Fragen in der Pr&uuml;fung vorkommen, die durch die Modulbeschreibung nicht gedeckt sind. Besteht ein Teil der Pr&uuml;fung bspw. daraus Threads anwenden zu k&ouml;nnen, obwohl diese nicht in der Modulbeschreibung auftauchen, sehe ich das als gravierenden Mangel an. <strong>Die Modulbeschreibungen sind bindend<\/strong>, eine Pr&uuml;fung soll nur diejenigen Kompetenzen pr&uuml;fen, die das Modul laut Modulbeschreibung vermitteln soll. Das Verwaltungsrecht kennt aber zwei verschiedene Verfahren:<\/p>\n<p><strong>Widerspruch&nbsp;<\/strong>Ein Widerspruch l&auml;sst euch die M&ouml;glichkeit der sp&auml;teren gerichtlichen Klage, sollte er abgelehnt werden. Er kann neben der Heraussetzung der Note oder der Annulierung der Klausur aber auch zu einer Verschlechterung eurer Note f&uuml;hren. Der Pr&uuml;fungsausschuss ist ungebunden an euren Antragstext. Sollte der Widerspruch abgelehnt werden, bleibt die originale Note bestehen. Einige Universit&auml;ten erheben dann auch eine Geb&uuml;hr, meist zwischen 70 und 100 Euro.<\/p>\n<p><strong>&Uuml;berdenken&nbsp;<\/strong>Das &Uuml;berdenkenverfahren f&uuml;hrt dazu, dass der Verwaltungsakt &uuml;berpr&uuml;ft wird, also im konkreten Fall der Klausur, wird die Klausur erneut kontrolliert. Findet die neue Korrektur weitere Punkte, kann die Note verbessert werden. Eine Annulierung oder Verschlechterung kann hier nicht stattfinden. Das &Uuml;berdenkenverfahren ist nicht mit Kosten verbunden, allerdings sind mit einem abgeschlossenen &Uuml;berdenkenverfahren die Rechtsmittel aufgebraucht, der Weg zum Gericht bleibt euch hier versperrt.<\/p>\n<h3 id=\"abschliessendes\">Abschlie&szlig;endes<\/h3>\n<p>Einen Widerspruch gegen die Note oder gegen den Nicht-Bestehensbescheid bzw. ein &Uuml;berdenkenverfahren zu stellen ist erstmal etwas komisch. Im Normalfall sollte der Pr&uuml;fungsausschuss die Anonymit&auml;t der Studierenden gegen&uuml;ber der Pr&uuml;fer allerdings wahren. Auch sind Pr&uuml;fungsausschussmitglieder gegen die sich ein Antrag richtet von der \"Verhandlung\" ausgeschlossen (Befangenheit, &sect;20, &sect;21 VwVfG).<\/p>\n<p>Gleiches gilt &uuml;brigens f&uuml;r Pr&uuml;fer, die sich nicht unvoreingenommen gegen&uuml;ber (allen) Pr&uuml;flingen zeigen. Bspw. w&auml;re denkbar, dass ein Pr&uuml;fer Frauen in einer m&uuml;ndlichen Pr&uuml;fung grunds&auml;tzlich h&auml;rter bewertet.&nbsp;Dann w&auml;re eine Anfechtung wegen Befangenheit des Pr&uuml;fers denkbar, schlie&szlig;lich urteilt sie nicht mehr unvoreingenommen, sondern nimmt dann &Auml;u&szlig;erlichkeiten in die Bewertung einer Pr&uuml;fung hinein.<\/p>\n<p>Die Besprechung des Pr&uuml;fungsausschusses sieht meist so aus, dass der Antrag von jemandem vorgestellt wird, die Mitglieder dar&uuml;ber diskutieren (also auch was genau getan werden sollte) und zum Schluss &uuml;ber den Antrag abstimmen. Der Pr&uuml;fungsausschuss kann auch von sich heraus aktiv werden, an den meisten Universit&auml;ten wird das aber nicht passieren. Der Pr&uuml;fungsausschuss hat die Untersuchungspflicht und ist dabei nicht an euren Antrag gebunden, d.h. er kann sobald er den Antrag hat, die Faktenlage genauer anschauen, auch in Bereiche, die euer Antrag nicht umfasst.<\/p>\n<p>F&uuml;r Manche f&uuml;hlt sich das sicher so an, als w&uuml;rde man sich \"durch eine Pr&uuml;fung durchklagen\", also so lange mit Gerichten und Anw&auml;lten drohen, bis man irgendwann doch bestanden hat. Tats&auml;chlich stellt sich die Situation anders dar. Es spricht m.A.n. nichts dagegen Pr&uuml;fungsverfahren auf M&auml;ngel untersuchen zu lassen. Der Pr&uuml;fungsausschuss ist dabei allerdings auf eure Begr&uuml;ndung angewiesen. Weiter kann der Pr&uuml;fungsausschuss die Beteiligten anh&ouml;ren (meistens schriftlich) bevor er sich eine abschlie&szlig;ende Meinung bildet. Die wenigsten Aufsichten fertigen ein Pr&uuml;fungsprotokoll von schriftlichen Pr&uuml;fungen an, d.h. letztendlich bleibt es Aussage gegen Aussage.<\/p>\n<p>Um den Pr&uuml;fungsausschuss etwas unter Druck zu setzen, k&ouml;nnt ihr auch andere Studierende ansprechen, die ebenfalls diese Pr&uuml;fung mitgeschrieben \/ mitgemacht haben. Der Pr&uuml;fungsausschuss hat sonst die Eigenschaft eine einzelne Anfechtung als weniger gewichtig zu werten, besonders wenn es um eher subjektive Themen geht, wie die Menge der Aufgaben f&uuml;r die Pr&uuml;fungszeit.<\/p>\n<p><strong>&Uuml;ber mich<\/strong><\/p>\n<p>Ich bin seit mittlerweile zwei Jahren im Pr&uuml;fungsausschuss der Studieng&auml;nge der Fakult&auml;t Informatik an der TU Chemnitz. Zuvor habe ich mich haupts&auml;chlich \"von Weitem\" mit Studieng&auml;ngen und Studienkommissionen, StuRa und Fachschaftsrat besch&auml;ftigt. Ich habe an verschiedenen Schulungsangeboten des StuRa teilgenommen und lese mich nach und nach selbst durch das s&auml;chs. HSFG oder aktuell die l&auml;ngergemeinsamen Strukturvorgaben. Ich studiere aktuell im Masterstudiengang Informatik.<\/p>","category":[{"@attributes":{"term":"Studium"}},{"@attributes":{"term":"Befangenheit"}},{"@attributes":{"term":"Klausur"}},{"@attributes":{"term":"Pr\u00fcfer"}},{"@attributes":{"term":"Pr\u00fcfungsrecht"}},{"@attributes":{"term":"Studium"}},{"@attributes":{"term":"\u00dcberdenken"}},{"@attributes":{"term":"Universit\u00e4t"}},{"@attributes":{"term":"Verwaltungsrecht"}},{"@attributes":{"term":"VwVfG"}},{"@attributes":{"term":"Widerspruch"}}]},{"title":"Porting Micropython to bare-metal Raspberry Pi","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/porting-micropython-to-bare-metal-raspberry-pi.html","rel":"alternate"}},"published":"2017-12-27T12:12:00+01:00","updated":"2017-12-27T12:12:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-12-27:\/informatik\/porting-micropython-to-bare-metal-raspberry-pi.html","summary":"<p>In the last months I ported Micropython to the Raspberry Pi. Micropython is an embedded Python interpreter, which already runs on ARM Cortex-M processors. I had to understand the build process, alter it as to target the Raspberry Pi processor and fix some annoying bugs and glitches. The result is \u2026<\/p>","content":"<p>In the last months I ported Micropython to the Raspberry Pi. Micropython is an embedded Python interpreter, which already runs on ARM Cortex-M processors. I had to understand the build process, alter it as to target the Raspberry Pi processor and fix some annoying bugs and glitches. The result is a port of Micropython which can execute Python code on the Raspberry Pi bare-metal. The port however only targets the Raspberry Pi 1 and Raspberry Pi Zero, with the ARM1176jzf-s processor. Porting to the Pi2 or Pi3 should not be that hard, as they feature an ARM Cortex-A processor.<\/p>\n<p>The paper enclosed is the written work submitted for grading to the Operating System Group [1] at TU Chemnitz. Also I edited a schematic of the Raspberry Pi Zero to include the numbers of the pins in its GPIO-pinheader, which can be downloaded and used freely. The port can be found in [2] (as long as it is not merged).<\/p>\n<p>The term paper can be found <a href=\"\/static\/resources\/2017-12-mpy.pdf\">here<\/a>. The Raspberry Pi Zero schematic can be downloaded <a href=\"\/static\/resources\/2017-12-rpi-zero.svg\">here<\/a>.<\/p>\n<p>[1] <a href=\"https:\/\/osg.informatik.tu-chemnitz.de\">https:\/\/osg.informatik.tu-chemnitz.de<\/a><br\/>\n[2] <a href=\"https:\/\/github.com\/naums\/micropython\">https:\/\/github.com\/naums\/micropython<\/a><\/p>\n<p><a href=\"\/static\/resources\/2017-12-rpi-zero.svg\"><img alt=\"Schematic of the Raspberry Pi Zero with GPIO-Names\" src=\"\/static\/resources\/2017-12-rpi-zero.svg\" width=\"100%\"\/><\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"ARM"}},{"@attributes":{"term":"ARM1176jzf-s"}},{"@attributes":{"term":"Bare Metal"}},{"@attributes":{"term":"Interpreter"}},{"@attributes":{"term":"Micropython"}},{"@attributes":{"term":"Python"}},{"@attributes":{"term":"Raspberry Pi"}}]},{"title":"KiF 45,5 in Duisburg - Meine Eindr\u00fccke","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/kif-455-in-duisburg-meine-eindruecke.html","rel":"alternate"}},"published":"2017-11-27T12:37:00+01:00","updated":"2017-11-27T12:37:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-11-27:\/informatik\/kif-455-in-duisburg-meine-eindruecke.html","summary":"<p>Die Konferenz der Informatik Fachschaften (kurz KiF) findet halbj&auml;hrlich statt und wird jeweils von einer anderen Informatik-Fachschaft im Bundesgebiet ausgerichtet. Die KiF 45,5 in Duisburg war meine erste KiF, deshalb hat der Text keinen Anspruch auf Richtigkeit und Vollst&auml;ndigkeit. Sollte ich etwas falsch verstanden haben, bitte Bescheid geben.<\/p>\n<h3 id=\"vorher\">Vorher \u2026<\/h3>","content":"<p>Die Konferenz der Informatik Fachschaften (kurz KiF) findet halbj&auml;hrlich statt und wird jeweils von einer anderen Informatik-Fachschaft im Bundesgebiet ausgerichtet. Die KiF 45,5 in Duisburg war meine erste KiF, deshalb hat der Text keinen Anspruch auf Richtigkeit und Vollst&auml;ndigkeit. Sollte ich etwas falsch verstanden haben, bitte Bescheid geben.<\/p>\n<h3 id=\"vorher\">Vorher<\/h3>\n<p>Ich wurde schon drei oder vier mal vorher gefragt, ob ich nicht mit zu einer KiF fahren wolle, musste aber jedesmal ablehnen. Jetzt endlich mal teilnehmen zu k&ouml;nnen ist sch&ouml;n. Fr&uuml;her waren es meistens Terminkonflikte, die Anmeldung war da schon rum, oder ich konnte mich einfach nicht festlegen. Das Erste, was ich eventuellen Erstkiffels empfehlen kann: tuts einfach. Springt in das kalte Wasser, in das Ungewisse und meldet euch an - idealerweise in einer Gruppe und noch besser auch mit Altkiffels, die bescheid wissen. Ihr m&uuml;sst auf der KiF nicht st&auml;ndig zusammenhocken, aber es ist immer gut jemanden zu haben, der einem Zeug erkl&auml;ren kann.<\/p>\n<p>Der Blick ins KiF-Wiki ist nicht zu vernachl&auml;ssigen. Die Infos dort sind aber zum Zeitpunkt vor der Anreise nicht sehr vollst&auml;ndig. Ein Blick ins Infoheft hat mir viel erkl&auml;rt aber Einiges ist halt doch noch offen, wie beispielsweise die Arbeitskreise und wann sie stattfinden. Das liegt aber in der Natur der KiF, weil die Arbeitskreise erst auf dem Anfangsplenum diskutiert werden und in der Nacht vom ersten auf den zweiten Tag geplant werden. Auf der KiF in Duisburg wurden Unterk&uuml;nfte gestellt - in Form von Zelten. Das ist im November nicht ganz ideal, aber immer noch besser als gar nichts. Normalerweise werden Unterk&uuml;nfte wohl auch gestellt, wie man mir sagte. Packt euch also einen warmen Schlafsack, eine Isomatte, Luftmatratze oder Feldbett, und\/oder ein Kissen\/Kuscheldecke ein - vor allem f&uuml;r die Winter\/Herbst-KiF.<\/p>\n<p>Lasst euch auch vom Wiki nicht erschlagen. Ein Wiki, was &uuml;ber Jahre hinweg \"gepflegt\" wird, ist un&uuml;bersichtlich, &uuml;berall stehen Informationen und es ist kaum m&ouml;glich alles zu finden oder zu lesen. Im Wiki steht alles, das aber zu finden ist nicht ganz trivial. Ihr k&ouml;nnt nicht nur die Orga fragen, sondern auch Altkiffel. Ein Blick in die Packliste hilft beim Packen &uuml;brigens ungemein, wenn ihr Angst habt etwas wichtiges zu vergessen.<\/p>\n<h3 id=\"tag-der-anreise\">Tag der Anreise<\/h3>\n<p>\"Habe ich alles? Oh verdammt schon so sp&auml;t, Mist meine Bahn f&auml;hrt grade nicht zum Hauptbahnhof, dann laufe ich eben.\" - so ging es mir am Anreisetag. Die Zugfahrt dauerte von Chemnitz nach Duisburg ziemlich lange, die meiste Zeit haben wir geschlafen, Musik geh&ouml;rt, B&uuml;cher gelesen, etc. Packt euch also gen&uuml;gend Musik, Akku(s), B&uuml;cher, bla ein - also irgendwas zu tun, wenn ihr im Zug wach bleiben wollt. Die meiste Zeit hat das auch gut geklappt bei unserer Zugfahrt, die Bahnen waren gr&ouml;&szlig;tenteils recht leer, sodass auch ein Hinlegen &uuml;ber zwei Pl&auml;tze nicht sonderlich schwierig war. Bequem war das aber dennoch nicht.<\/p>\n<p>Angekommen in Duisburg sind wir dann zur Uni gelaufen, das ging in dem Fall, ist aber sicher nicht in jeder Stadt ohne Weiteres m&ouml;glich (oder sinnvoll). Im Geb&auml;ude angekommen wurde ich von einem eher linken Flaire erf&uuml;llt. Im Asta-Keller waren die W&auml;nde beschrieben und bemalt. Die Unisex-Toilettenr&auml;ume (von denen es eine Variante mit und eine ohne Stand-Toiletten gab) waren ebenfalls gut geschm&uuml;ckt. Das machte auf mich einen eher ungereinigten Eindruck, ich hatte aber nicht das Gef&uuml;hl, dass das unglaublich schlimm w&auml;re.<\/p>\n<p>Schnell ein Br&ouml;tchen vom ewigen Fr&uuml;hst&uuml;ck geschnappt, Sachen irgendwo hin getan, die ich noch bei mir hatte (einiges wurde vom Hbf in Duisburg direkt mit einem Auto zur Uni gefahren) und dann ging es auch schon zum Erstkiffelplenum. Dort wird kurz erkl&auml;rt was die KiF ist, wie sie funktioniert und es werden auch die Handzeichen erkl&auml;rt. Beispielsweise gibt es auf der KiF eigentlich keinen Applaus, sondern daf&uuml;r werden die H&auml;nde gehoben und gesch&uuml;ttelt \/ gedreht. Eine Meta-Meldung funktioniert wie ein GO-Antrag mit beiden H&auml;nden in&nbsp; der Luft, f&uuml;hrt allerdings nicht zu einem Verfahrensantrag, sondern ist eine Meldung, die dazu f&uuml;hren soll bspw. die Fenster zu &ouml;ffnen. Weitere Zeichen: Falsche Fakten, die Diskussion f&auml;llt aus dem Rahmen oder Veto k&ouml;nnen auch im KiF-Wiki gefunden werden.<\/p>\n<p>Das Anfangsplenum war sehr interessant. Nach einigen Orga-Hinweisen wurden dann die Fachschaften vorgestellt, d.h. die Kiffel sagen etwas &uuml;ber ihre Fachschaft. F&uuml;r mich ist es immer noch sehr befremdlich in ein Mikro reinzusprechen und ich glaube das hat man gemerkt. Wenn ihr Altkiffel dabei habt, werdet ihr aber nicht dazu gezwungen etwas zu sagen (weil nur irgendjemand etwas sagen soll). Danach kommt die Vorstellung der AKs. Dazu werden die Arbeitskreise ins Wiki eingetragen. Nach einer bestimmten Frist werden daraus Folien erzeugt und alle AKs werden kurz vorgestellt und ein Interesse abgefragt, also abgefragt, wie viele Leute daran gern teilnehmen wollen. Auch AKs, die nicht im Wiki stehen k&ouml;nnen noch spontan eingebracht werden. Hier empfiehlt sich das Mitbringen eines eigenen Laptop, weil im Wiki mit dem Smartphone zu schreiben nicht sch&ouml;n ist.<\/p>\n<p>Die AKs teilen sich dabei in Arbeits-AKs und Spa&szlig;-AKs, letztere finden Abends statt, sind aber nicht immer komplett spa&szlig;ig, wie die Bier-AK, sondern k&ouml;nnen auch eher Selbsthilfegruppen-Charakter haben. Sucht euch AKs aus, meldet euch bei Interesse und hofft dann, dass der Schedule der AKs euch erm&ouml;glicht so viele wie m&ouml;glich davon auch wirklich zu besuchen.<\/p>\n<p>Nach dem Anfangsplenum wird dann gesocialized. Dazu gibt es das KiF-Cafe, was in Duisburg direkt neben dem ewigen&nbsp; Fr&uuml;hst&uuml;ck lag. Das ewige Fr&uuml;hst&uuml;ck ist genau das. Ihr bekommt dort Br&ouml;tchen, k&ouml;nnte die Aufschneiden und mit Unmengen Zeug belegen. Weiter gibt es Kaffee, Tee, S&auml;fte, diesmal auch Fassbier, etc. Gegen Geld konnte man sich auch Softdrinks, Mate oder anderes Bier kaufen.<\/p>\n<p>Zu diesem Zeitpunkt ging es mir so, dass ich mich da sehr ausgeschlossen gef&uuml;hlt habe, weil ich dachte, quasi jeder kennt hier schon jeden und mich da zu integrieren wird schwer. Das ist es nicht. Als Erstkiffel solltet ihr mit vielen vielen Leuten reden. Wenn es euch schwer f&auml;llt Leute anzusprechen, hilft es euch vielleicht Fragen bereitzulegen, wie bspw. \"Wie hei&szlig;t du? Wo kommst du her? Wie ist bei euch so die Fachschaft drauf?\". Das hilft viel.<\/p>\n<p>Dann ging es irgendwann in den Schlafsack und verdammt war es diese Nacht kalt im Zelt - Memo: besseren Schlafsack zu Winter-KiFs mitbringen.<\/p>\n<h3 id=\"aks-und-so-zeugs-zwischen-anreise-und-abreise\">AKs und so Zeugs zwischen Anreise und Abreise<\/h3>\n<p>Die AKs haben ein Leitkiffel. Dieses Kiffel leitet die Diskussion und formuliert Eingangs auch meist eine mehr oder weniger genaue Frage, mit der sich die AK besch&auml;ftigen soll. Dann gibt es Diskussion, meist auch einen Faktenbericht aus den einzelnen Fachschaften wie bspw. \"bei uns ist das \\&lt;so&gt;\". Einige AKs arbeiten auch an Resolutionen, also Beschl&uuml;ssen, die die KiF fassen kann, um damit Forderungen auszudr&uuml;cken. Diese Forderungen k&ouml;nnen dann als offener Brief von der KiF an Politiker, etc. geschickt werden und werden ver&ouml;ffentlicht. Eine KiF beschlie&szlig;t keine Resolutionen zu Themen der KiF-Organisation.<\/p>\n<p>Einige AKs sind eher Workshop-m&auml;&szlig;ig, anderer eher eine freie Diskussion und Bestandsaufnahme. Hier kommt es darauf an, dass ihr euch einbringt, und nachfragt, wenn ihr etwas nicht verstanden habt. Die anderen Kiffel bei&szlig;en nicht - was euch im Laufe der KiF immer klarer werden sollte. Die meisten von denen sind sogar total freundlich und hinreichend r&uuml;cksichtsvoll.<\/p>\n<p>Am Dienstag fand eine Stadttour statt, die Duisburg so ein bisschen gezeigt hat, also quasi mal etwas mehr als nur das Unigel&auml;nde. Das war ziemlich cool auch mal andere Sachen zu sehen ;). Es gibt auch Fackell&auml;ufe oder andere Dinge, die ihr machen k&ouml;nnt, wenn euch grade nicht nach AK ist. Dazu mal ins Infoheft schauen oder im Wiki vorher informieren, was angeboten wird und ob ihr da Lust drauf habt. Die Infos vorab &auml;ndern sich zwar ab und an noch, aber &Auml;nderungen k&ouml;nnt ihr jederzeit auf der KiF bspw. im KiF-Cafe erfragen.<\/p>\n<p>Am Abend finden dann Spa&szlig;-AKs statt, die einen Rahmen f&uuml;r Socializing bieten k&ouml;nnen, andererseits auch Erfahrungsaustausch zu psychischen Problemen oder Themen wie BDSM und Polyamorie. Hier k&ouml;nnt ihr Dinge von euch erz&auml;hlen, die die anderen r&uuml;cksichtsvoll beantworten, oder euch Hinweise geben. Habt ihr Fragen zum Fesseln? Dann fragt in der entsprechenden AK Schweinskram. In den Spa&szlig;-AKs geht es dann zwar nicht um Spa&szlig;, aber um Dinge, die nicht an sich informatischer Natur sind, dennoch sind alle unheimlich r&uuml;cksichtsvoll, sodass Fragen und auch Probleme beantwortet werden k&ouml;nnen. Und nat&uuml;rlich kann auch eine solche Spa&szlig;-AK der Platz sein Leute besser kennen zu lernen, ins Gespr&auml;ch zu kommen und Eis abzubauen.<\/p>\n<p>Ich habe die KiF als sehr offenes Treffen von Informatikern und tollen Menschen empfunden. Ohne alle zu kennen, kann man den Leuten dort vertrauen, jedenfalls habe ich das so wahrgenommen. Zu mir waren alle unglaublich freundlich. Im &Uuml;brigen haben die meisten Kiffel keine Ber&uuml;hrungs&auml;ngste - die meisten freuen sich &uuml;ber Flausch - wenn ihr euch unsicher seid lieber vorher mal nachfragen. Die meisten Kiffel sind recht entspannt drauf, aber Grenzen &uuml;bertreten gef&auml;llt trotzdem Niemandem.<\/p>\n<p><strong>Ganz wichtig<\/strong>: eine KiF ist ein riesengro&szlig;er Haufen Menschen. Viele, wie auch ich, haben Probleme mit vielen Menschen und da auch Probleme sich in Gruppen und Kreisen zu integrieren. Es ist einfach sich einsam zu f&uuml;hlen - das seid ihr nicht. Traut euch, geht zu Leuten hin, geht zu Gruppen hin, sprecht mit Leuten. Wenn ihr alleine auf dem Boden rumsitzt wird sich recht schnell jemand zu euch setzen, denn Gruppen sind unglaublich dynamisch auf der KiF.<\/p>\n<h3 id=\"abreise\">Abreise<\/h3>\n<p>Echt gemein, dass eine KiF enden muss. Die ewige R&uuml;ckfahrt, auf der ich dann auch noch den Anschlusszug in Kassel verpasst habe und dort zwei verkackte Stunden auf den Zug warten musste, war dann eher m&auml;h. Da ihr aber so viel Schlaf auf der KiF verpasst habt, schlaft ihr auf der R&uuml;ckfahrt dann ohnehin total viel. Es ist es ein Kulturschock von einer Ort mit so vielen tollen Menschen wieder nach Hause zu m&uuml;ssen, wo man wieder allein ist und wo nicht &uuml;berall so tolle Leute rumlaufen. Ich freue mich jetzt darauf in Vorlesungen und &Uuml;bungen Zeichen wie Meta und falsche Fakten zu benutzen. Wenn ich kann (das steht bei mir noch nicht ganz fest), will ich auch wieder nach Bremen mitkommen!<\/p>\n<p><a href=\"\/data\/thumbnail\/kif01_full.jpg\"><img alt=\"Kif Duisburg\" class=\"hover_img\" src=\"\/data\/thumbnail\/kif01_large.jpg\" width=\"49%\"\/><\/a>\n<a href=\"\/data\/thumbnail\/kif02_full.jpg\"><img alt=\"Kif Duisburg\" class=\"hover_img\" src=\"\/data\/thumbnail\/kif02_large.jpg\" width=\"49%\"\/><\/a>\n<a href=\"\/data\/thumbnail\/kif03_full.jpg\"><img alt=\"Kif Duisburg\" class=\"hover_img\" src=\"\/data\/thumbnail\/kif03_large.jpg\" width=\"49%\"\/><\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Asta"}},{"@attributes":{"term":"Dusiburg"}},{"@attributes":{"term":"Fachschaft"}},{"@attributes":{"term":"FSR"}},{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"kif"}},{"@attributes":{"term":"Kif455"}},{"@attributes":{"term":"Konferenz"}},{"@attributes":{"term":"Sozial"}},{"@attributes":{"term":"StuPa"}},{"@attributes":{"term":"StuRa"}},{"@attributes":{"term":"Uni"}}]},{"title":"Controlling features of the ARM1176jzf-s (Raspberry Pi)","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/controlling-features-of-the-arm1176jzf-s-raspberry-pi.html","rel":"alternate"}},"published":"2017-08-15T20:32:00+02:00","updated":"2017-08-15T20:32:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-08-15:\/informatik\/controlling-features-of-the-arm1176jzf-s-raspberry-pi.html","summary":"<p>This article is about the Raspberry Pis Processor, the ARM1176jzf-s. It is a 32 Bit ARM-processor, with ARMv6-architecture. It has a VFPv2 Floating Point Unit, can run Java Bytecode natively (Jazelle), can run Thumb(1) code, can use both little and big endian-data, has an MMU and many things more \u2026<\/p>","content":"<p>This article is about the Raspberry Pis Processor, the ARM1176jzf-s. It is a 32 Bit ARM-processor, with ARMv6-architecture. It has a VFPv2 Floating Point Unit, can run Java Bytecode natively (Jazelle), can run Thumb(1) code, can use both little and big endian-data, has an MMU and many things more. This article will only talk about some basics of controlling the processor state and features.<\/p>\n<h2 id=\"program-status-register-cpsr\">Program status register (CPSR)<\/h2>\n<p>The CPSR [1] contains flags for the most integral features of the ARM-processor. These are the Jazelle and Thumb state bit, Interrupt and Fast Interrupt disable bits, privilege mode bits [2] and condition bits, which indicate the results of the last test or compare-instruction.<\/p>\n<h3 id=\"reading-and-modifying-the-cpsr\">Reading and modifying the CPSR<\/h3>\n<p>One cannot read or modify the CPSR with the regular <em>mov<\/em> or <em>ldr<\/em>\/<em>str<\/em> instructions. Use the following instructions for reading and writing data from or to the state register:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">mrs<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr<\/span><span class=\"w\">    <\/span><span class=\"c1\">\/\/ read cpsr into r0<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">msr<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"w\">    <\/span><span class=\"c1\">\/\/ write r0 to cpsr<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Be aware, that not all bits can be modified by these instructions or should be modified by these instructions or require a privileged mode for modification.<\/p>\n<h3 id=\"the-flags\">The flags<\/h3>\n<p>[1] shows the bits of the CPSR register. There are the condition bits, which I will not be covering here, Jazelle state bit, Endianess, Imprecise abort disable, IRQ and FIQ disable, Thumb state bit and the mode bits. So let's suppose we want to switch to a different mode, like the IRQ-mode, set a stack and return to our previous mode (like the supervisor mode). [3] shows the bit representation of the different modes.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ first read the cpsr register into r0<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mrs<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ set the bits last 5 bits to 0<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">bic<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mh\">0x1f<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ set the appropriate mode bits (0x12 = 0b10010, IRQ mode)<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">orr<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mh\">0x12<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ write the value to cpsr<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">msr<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ set the irq-stack (with a predefined label)<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"n\">irq_stack_top<\/span><span class=\"w\">    <\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ enable interrupts and return to supervisor mode<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">bic<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mh\">0x80<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">msr<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>But how can I switch into Jazelle or Thumb-State? You probably already noted, that the <em>msr<\/em> and <em>mrs<\/em> instructions should never change the T and J-bits, meaning, that trying to switch into Thumb or Jazelle mode this way will probably result in unpredictable behaviour, i.e. code that does not work as you wanted. [4] depicts the way to jump into Thumb or Jazelle-code: the instructions <em>bx<\/em> and <em>bxj<\/em>. These are branch-instructions, which jump into a function, which is compiled as Thumb or Java-Bytecode code. I have yet to try both Thumb and Jazelle.<\/p>\n<h2 id=\"what-about-mmu-caches-branch-prediction_1\">What about MMU, Caches, Branch Prediction?<\/h2>\n<p>Well, enabling the MMU, caches or the branch prediction is in fact not done by the CPSR, but the system control coprocessor. [5] lists its registers.&nbsp;The system control coprocessor has to many features for me to list them here in any way, so take a look into [5]. There are functions to identify the processor and version as well as it's features, there are bits to enable features of the processor, like unaligned access to data, endianess, enabling data and instruction cache on Level 1 or setting the base address for the MMUs translation tables. <em>Hint: Enabling caches without the MMU will probably have no effect, as no page is marked as cacheable, or it could in fact cache registers of I\/O-devices, which you would never expect happening. So, just don't!<\/em><\/p>\n<h3 id=\"accessing-the-registers-of-the-system-control-coprocessor\">Accessing the registers of the System Control Coprocessor<\/h3>\n<p>You probably already guessed: the registers of the C15-coprocessor cannot be changed by <em>mov<\/em> or <em>ldr<\/em>\/<em>str<\/em> either. For accessing these registers we use the&nbsp;<em>mrc<\/em> and&nbsp;<em>mcr<\/em> instructions like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/\/ load C15 control register 0,c1,c0,0 into r0<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mrc<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ write r0 into C15 control register 0, c1, c0, 0<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Oh god, this looks terribly complicated. Yes, it kind of is, but not really. Let's assume <em>0,c1,c0,0<\/em> is an address. A rather unusual looking address, but nontheless it tells the processor which register of the C15-coprocessor should be written or read from. [5] lists the registers of the coprocessor with these addresses. Let's look up <em>0,c1,c0,0<\/em> - it's the control register. This register has flags for the MMU, Unaligned access, Caches and Branch predictions as well as many others, which I'm not quite sure what they do.<\/p>\n<h2 id=\"conclusions_1\">Conclusions<\/h2>\n<p>Accessing the CPSR as the central state register of the processor and the registers of the Control Coprocessor is unlike accessing the general purpose registers of the ARM, but it is not much more difficult. Using these registers is an integral part of programming the Raspberry Pi or the ARM1176jzf-s bare metal, as they allow accessing great features of the processor like the MMU or the Interrupt disable-states.<\/p>\n<p>A futures article will introduce the MMU of this processor (family), but for now a good introduction can be found under [6]. This text was originally written by David Welch, I rewrote it for readabilities sake and added explanations as well as bit-layout tables for easier understanding.<\/p>\n<h2 id=\"references\">References<\/h2>\n<p>[1] <a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/I2837.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/I2837.html<\/a><br\/>\n[2] <a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/Chdigebi.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/Chdigebi.html<\/a><br\/>\n[3]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch02s10s07.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch02s10s07.html<\/a><br\/>\n[4]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/I26052.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/I26052.html<\/a><br\/>\n[5]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch02s09s01.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch02s09s01.html<\/a><br\/>\n[6]&nbsp;<a href=\"https:\/\/github.com\/naums\/raspberrypi\/blob\/master\/mmu\/README.md\">https:\/\/github.com\/naums\/raspberrypi\/blob\/master\/mmu\/README.md<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"ARM"}},{"@attributes":{"term":"ARM11"}},{"@attributes":{"term":"ARM1176jzf-s"}},{"@attributes":{"term":"Bare Metal"}},{"@attributes":{"term":"Cache"}},{"@attributes":{"term":"Coprocessor"}},{"@attributes":{"term":"CPSR"}},{"@attributes":{"term":"MMU"}},{"@attributes":{"term":"PilotOS"}},{"@attributes":{"term":"PiOS"}},{"@attributes":{"term":"Program State Register"}},{"@attributes":{"term":"Raspberry Pi"}},{"@attributes":{"term":"System Control"}}]},{"title":"Adding a module to Micropython","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/adding-a-module-to-micropython.html","rel":"alternate"}},"published":"2017-07-24T01:25:00+02:00","updated":"2017-07-24T01:25:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-07-24:\/informatik\/adding-a-module-to-micropython.html","summary":"<p>Using Micropython on your own hardware, like I do on Raspberry Pi, is quite a challenge. First of all you have to port Micropython. But when it runs on your platform you will probably need some module for Python, to extent the language itself by some functionalities only accessible in \u2026<\/p>","content":"<p>Using Micropython on your own hardware, like I do on Raspberry Pi, is quite a challenge. First of all you have to port Micropython. But when it runs on your platform you will probably need some module for Python, to extent the language itself by some functionalities only accessible in C or Assembler. These could be I\/O-functionalities like writing to device-registers or gathering the state of your platform, or you may just want to write something you could do in Python in a compiled language for performance and\/or memory footprint reasons.<\/p>\n<p>This article shows how to add simple modules to Micropython. Please be aware, that I cannot show everything here, and it is just an example scenario. You are off course free to investigate the <em>stmhal<\/em>-port of Micropython to find some examples of bigger modules. This article mostly got its information from [1].<\/p>\n<h3 id=\"adding-your-own-source-files\">Adding your own source-files<\/h3>\n<p>Adding C source files is easy enough. Have a look into the <em>Makefile<\/em>&nbsp;of the port you want to use. You will find a part which lists all of the source-files used to compile the specific port. This looks like this (from&nbsp;<em>bare-rpi\/Makefile<\/em>):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"nv\">SRC_C<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\">   <\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"k\">$(<\/span>SRC<span class=\"k\">)<\/span>main.c<span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"k\">$(<\/span>SRC<span class=\"k\">)<\/span>irq.c<span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"k\">$(<\/span>SRC<span class=\"k\">)<\/span>module_rawptr.c<span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"k\">$(<\/span>SRC<span class=\"k\">)<\/span>module_cdebug.c<span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"k\">$(<\/span>SRC<span class=\"k\">)<\/span>module_cio.c<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This example uses five C-files to build the port, three of which coincidentally&nbsp;add modules already. Create a source-file and add its name to the list of C-files. Be sure to use a relative path from the Makefile.<\/p>\n<p>When using a platform with very limited (instruction) RAM be aware of the following [1]:<\/p>\n<blockquote>\n<p>The second file you will need to add to is <em>esp8266.ld<\/em>, which is the map of memory used by the compiler. You have to add it to the list of files to be put in the <em>.irom0.text<\/em> section, so that your code goes into the instruction read-only memory (<em>iROM<\/em>). If you fail to do that, the compiler will try to put it in the instruction random-access memory (<em>iRAM<\/em>), which is a very scarce resource, and which can get overflown if you try to put too much there.<\/p>\n<\/blockquote>\n<h3 id=\"create-a-first-module\">Create a first module<\/h3>\n<p>To create an empty Micropython module we need to use the type&nbsp;<em>mp_obj_module_t<\/em>, which is the type of the modules in Micropython. This type wants a property which defines its base and a dictionary of globally defined names. Let's add the following code to our file:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/mpconfig.h\"<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/nlr.h\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/misc.h\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/qstr.h\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/obj.h\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/runtime.h\"<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ create a table of global strings, here the only one is name<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_map_elem_t<\/span><span class=\"w\"> <\/span><span class=\"n\">global_table<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR___name__<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_mymodule<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ create a dictionary of strings from the table<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"nf\">MP_DEFINE_CONST_DICT<\/span><span class=\"p\">(<\/span><span class=\"n\">mymodule_globals<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">global_table<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ fill the mp_obj_module_t struct, which defines the module itself<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_module_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">base<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_type_module<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">globals<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_dict_t<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mymodule_globals<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This code create an \"empty\" module for Micropython. It fills the <em>mp_obj_module_t<\/em>-struct with the bare-minimum of information to be loadable by Micropython. The only thing in its global-dictionary is the string \"mymodule\". You have to add this name to the list of QStrings manually. Add the following line to the file&nbsp;<em>qstrdefsport.h<\/em>:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">Q<\/span><span class=\"p\">(<\/span><span class=\"n\">mymodule<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Micropython can't just load the module by itself, it has to be told which modules exist and which modules you want to have built into the kernel\/firmware. This can be done by adding it to the list of BUILTIN Modules in&nbsp;<em>mpconfigport.h<\/em>:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_module_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule<\/span><span class=\"p\">;<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define MICROPY_PORT_BUILTIN_MODULES  <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">       <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_myfirstmodule<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">)<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mymodule<\/span><span class=\"w\"> <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The first line shows the C-Compiler, that there is (or at least will be) a variable called&nbsp;<em>mymodule<\/em> when linking. This does not instantiate the variable itself, but rather tell the C-Compiler, that this variable will be defined and instantiated in another C-file. This line could also be put into a separate header-file.<\/p>\n<p>The third and fourth lines are more interesting. The preprocessor-constant <em>MICROPY_PORT_BUILTIN_MODULES&nbsp;<\/em>tells the build-process which modules will be built in and will be callable from inside a Python-script. The first parameter will be the name of the module, which you need to load it from the script, the second one is the module-variable we filled earlier.<\/p>\n<p>Loading this empty module from inside a Python-script can be done by:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">myfirstmodule<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"add-a-function\">Add a function<\/h3>\n<p>As a first function in our module it would be nice to have one, which prints \"Hello World\", would it not? So let's define a C-function which does exactly that in the file of our module from earlier:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdio.h&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">printf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Hello world!<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_none<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This is not quite your normal \"Hello &nbsp;World\"-program, is it? At first it returns an&nbsp;<em>mp_obj_t<\/em> - a Python-object. The return value, which will actually be returned is&nbsp;<em>mp_const_none<\/em>.<\/p>\n<h4 id=\"a-bit-more-technical\">A bit more technical<\/h4>\n<p>So let's look up those two things in the Micropython-code:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ This is the definition of the opaque MicroPython object type.<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ All concrete objects have an encoding within this type and the<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ particular encoding is specified by MICROPY_OBJ_REPR.<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint64_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"kt\">uint64_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_obj_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#else<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">mp_const_obj_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#endif<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>First off this is the definition of&nbsp;<em>mp_obj_t<\/em>. In the most simple way, this is a void-pointer, so a pointer without compile-time information about its type. So it is basically a blanko-check with no questions asked, when you or the Micropython-code want(s) to access it. Behind this pointer could be anything.<\/p>\n<p>Now the&nbsp;<em>mp_const_none<\/em>:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ Constant objects, globally accessible<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ The macros are for convenience only<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define mp_const_none (MP_OBJ_FROM_PTR(&amp;mp_const_none_obj))<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define mp_const_false (MP_OBJ_FROM_PTR(&amp;mp_const_false_obj))<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define mp_const_true (MP_OBJ_FROM_PTR(&amp;mp_const_true_obj))<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&amp;mp_const_empty_bytes_obj))<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&amp;mp_const_empty_tuple_obj))<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_none_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_none_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_bool_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_false_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_bool_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_true_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_str_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_empty_bytes_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_tuple_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_empty_tuple_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_singleton_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_ellipsis_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_singleton_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_notimplemented_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_exception_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_MemoryError_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">extern<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_exception_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_GeneratorExit_obj<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;stdlib.h&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/nlr.h\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/obj.h\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"py\/runtime0.h\"<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_none_t<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mp_obj_base_t<\/span><span class=\"w\"> <\/span><span class=\"n\">base<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_none_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">none_print<\/span><span class=\"p\">(<\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_print_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">print<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">self_in<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_print_kind_t<\/span><span class=\"w\"> <\/span><span class=\"n\">kind<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><span class=\"n\">self_in<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">MICROPY_PY_UJSON<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;&amp;<\/span><span class=\"w\"> <\/span><span class=\"n\">kind<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"n\">PRINT_JSON<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_print_str<\/span><span class=\"p\">(<\/span><span class=\"n\">print<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"null\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_print_str<\/span><span class=\"p\">(<\/span><span class=\"n\">print<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"None\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_type_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_type_NoneType<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_type_type<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_QSTR_NoneType<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">print<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">none_print<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">unary_op<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_generic_unary_op<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_none_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_none_obj<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{{<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_type_NoneType<\/span><span class=\"p\">}};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><em>mp_const_none<\/em> is a preprocessor-statement, which will be substituted to a pointer to&nbsp;<em>mp_const_none_obj<\/em> which in turn is an Python-object of&nbsp;<em>mp_type_NoneType<\/em>, which only has a <em>print<\/em>-function, that prints either \"null\" or \"None\". I don't want to go into more of a detail here.<\/p>\n<h4 id=\"back-to-our-function\">Back to our function<\/h4>\n<p>For us to being able to use the function, we need to create a constant function-object. This is done by&nbsp;<em>MP_DEFINE_CONST_FUN_OBJ_0.&nbsp;<\/em>The last number stands for the number of arguments, this function will get. Our function does not want any arguments, so we will use 0:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"nf\">MP_DEFINE_CONST_FUN_OBJ_0<\/span><span class=\"p\">(<\/span><span class=\"n\">mymodule_hello_obj<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello<\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Adding this function to our module is now quite easy, as we only need to add it to the global-names, so lets extent the global_table-variable from earlier:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_map_elem_t<\/span><span class=\"w\"> <\/span><span class=\"n\">global_table<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR___name__<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_mymodule<\/span><span class=\"p\">)<\/span><span class=\"w\">  <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_hello<\/span><span class=\"p\">),<\/span><span class=\"w\">    <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_hello_obj<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This adds the object under the name \"hello\" to the dictionary of globally available functions of that module. We have to add the function to the list of QStrings again. Now it is possible to call our function by the following script:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kn\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">mymodule<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mymodule<\/span><span class=\"o\">.<\/span><span class=\"n\">hello<\/span><span class=\"p\">()<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"function-arguments_1\">Function arguments<\/h3>\n<p>You probably already guessed it - the arguments to function will be of&nbsp;<em>mp_obj_t<\/em> type. So let's create a new function which greets someone with his\/her actual name (when provided as argument):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_greet<\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">who<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">printf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Hello %s!<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_str_get_str<\/span><span class=\"p\">(<\/span><span class=\"n\">who<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_none<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_DEFINE_CONST_FUN_OBJ_1<\/span><span class=\"p\">(<\/span><span class=\"n\">mymodule_greet_obj<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_greet<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><em>mp_obj_str_get_str<\/em> receives a string-object (again:&nbsp;<em>mp_obj_t<\/em> itself is a void-pointer, the Micropython hopes to find a suitable struct at the end) and returns a C-string representation of the information stored inside. This function will btw. automatically raise a Python-exception if the type is not correct. Our function can be used to create a constant function-object with&nbsp;<em>MP_DEFINE_CONST_FUN_OBJ_1<\/em>, as it takes one argument.<\/p>\n<h4 id=\"digging-deeper\">Digging deeper<\/h4>\n<p>So what does&nbsp;<em>MP_DEFINE_CONST_FUN_OBJ_1<\/em> do exactly? I wanted to know and began digging:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name)   <\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">   <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_fun_builtin_fixed_t<\/span><span class=\"w\"> <\/span><span class=\"n\">obj_name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">       <\/span><span class=\"p\">{{<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_type_fun_builtin_0<\/span><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">fun<\/span><span class=\"p\">.<\/span><span class=\"n\">_0<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">fun_name<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name)   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">   <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_fun_builtin_fixed_t<\/span><span class=\"w\"> <\/span><span class=\"n\">obj_name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">       <\/span><span class=\"p\">{{<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_type_fun_builtin_1<\/span><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">fun<\/span><span class=\"p\">.<\/span><span class=\"n\">_1<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">fun_name<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name)   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">   <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_fun_builtin_fixed_t<\/span><span class=\"w\"> <\/span><span class=\"n\">obj_name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\">   <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">       <\/span><span class=\"p\">{{<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_type_fun_builtin_2<\/span><span class=\"p\">},<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">fun<\/span><span class=\"p\">.<\/span><span class=\"n\">_2<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">fun_name<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The macro will be substituted by the creation of a variable of the type&nbsp;<em>mp_obj_fun_builtin_fixed_t<\/em>. The type-attribute will be set accordingly to the number of arguments of the function and the sub-union&nbsp;<em>fun<\/em> will be used to set either the&nbsp;<em>_0<\/em>,&nbsp;<em>_1<\/em> or&nbsp;<em>_2<\/em>-attribute. The attributes share the same space in memory (see union). All of these attributes are of pointer-type to a function. The only distinguishing fact about these functions is the number of arguments.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">mp_fun_0_t<\/span><span class=\"p\">)(<\/span><span class=\"kt\">void<\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">mp_fun_1_t<\/span><span class=\"p\">)(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">mp_fun_2_t<\/span><span class=\"p\">)(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">mp_fun_3_t<\/span><span class=\"p\">)(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">mp_fun_var_t<\/span><span class=\"p\">)(<\/span><span class=\"kt\">size_t<\/span><span class=\"w\"> <\/span><span class=\"n\">n<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/\/ ... <\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mp_obj_fun_builtin_fixed_t<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mp_obj_base_t<\/span><span class=\"w\"> <\/span><span class=\"n\">base<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">union<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_fun_0_t<\/span><span class=\"w\"> <\/span><span class=\"n\">_0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_fun_1_t<\/span><span class=\"w\"> <\/span><span class=\"n\">_1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_fun_2_t<\/span><span class=\"w\"> <\/span><span class=\"n\">_2<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_fun_3_t<\/span><span class=\"w\"> <\/span><span class=\"n\">_3<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"n\">fun<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_fun_builtin_fixed_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"adding-a-class_1\">Adding a class<\/h3>\n<p>When adding a class we will have again to add the name of the class to the global name table of the module. But first we have to create the innards of the class itself. The class data itself is handled by a C-struct. This struct needs an&nbsp;<em>mp_obj_base_t<\/em>&nbsp;<em>base<\/em>-attribute. This will have some basic information like the type. Then you add every field you want to use within the class or objects, like this:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ this is the actual C-structure for our new object<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_mymodule_hello_obj_t<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mp_obj_base_t<\/span><span class=\"w\"> <\/span><span class=\"n\">base<\/span><span class=\"p\">;<\/span><span class=\"w\">         <\/span><span class=\"c1\">\/\/ base represents some basic information, like type<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint8_t<\/span><span class=\"w\"> <\/span><span class=\"n\">hello_number<\/span><span class=\"p\">;<\/span><span class=\"w\">       <\/span><span class=\"c1\">\/\/ a member created by us<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_obj_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This struct is not visible to Python in any way, but can be used within our C-functions and methods to access the data we want \/ need. See the methods below for more information on that.<\/p>\n<p>Now let's create the type of the object:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ creating the table of local members<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_rom_map_elem_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_locals_dict_table<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"nf\">MP_DEFINE_CONST_DICT<\/span><span class=\"p\">(<\/span><span class=\"n\">mymodule_hello_locals_dict<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_locals_dict_table<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ create the class-object itself<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_type_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_helloObj<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_type_type<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><span class=\"w\">                                          <\/span><span class=\"c1\">\/\/ \"inherit\" the type \"type\"<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_QSTR_helloObj<\/span><span class=\"p\">,<\/span><span class=\"w\">                                   <\/span><span class=\"c1\">\/\/ give it a name<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">print<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_print<\/span><span class=\"p\">,<\/span><span class=\"w\">                              <\/span><span class=\"c1\">\/\/ give it a print-function<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">make_new<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_make_new<\/span><span class=\"p\">,<\/span><span class=\"w\">                        <\/span><span class=\"c1\">\/\/ give it a constructor<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"n\">locals_dict<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_dict_t<\/span><span class=\"o\">*<\/span><span class=\"p\">)<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mymodule_hello_locals_dict<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/ and the local members<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This code first defines a local dictionary for the local members of the type. Then define the class-structure itself. A class always needs a name, a&nbsp;<em>new<\/em>, and a&nbsp;<em>print<\/em>-method. This is required by Python, so we also need to define those, like this (above the code above):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"nf\">mymodule_hello_make_new<\/span><span class=\"p\">(<\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_type_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">type<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">size_t<\/span><span class=\"w\"> <\/span><span class=\"n\">n_args<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">size_t<\/span><span class=\"w\"> <\/span><span class=\"n\">n_kw<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">args<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ this checks the number of arguments (min 1, max 1);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ on error -&gt; raise python exception<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mp_arg_check_num<\/span><span class=\"p\">(<\/span><span class=\"n\">n_args<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">n_kw<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ create a new object of our C-struct type<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mymodule_hello_obj_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">self<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">m_new_obj<\/span><span class=\"p\">(<\/span><span class=\"n\">mymodule_hello_obj_t<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ give it a type<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">self<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">base<\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mymodule_hello_type<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ set the member number with the first argument of the constructor<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">self<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">hello_number<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_get_int<\/span><span class=\"p\">(<\/span><span class=\"n\">args<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_FROM_PTR<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_print<\/span><span class=\"p\">(<\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_print_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">print<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">self_in<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_print_kind_t<\/span><span class=\"w\"> <\/span><span class=\"n\">kind<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ get a ptr to the C-struct of the object<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mymodule_hello_obj_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">self<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_TO_PTR<\/span><span class=\"p\">(<\/span><span class=\"n\">self_in<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ print the number<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">printf<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"Hello(%u)\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">self<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">hello_number<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The&nbsp;<em>new<\/em>-method will create a new object of the class-type. First it checks the number of arguments, then creates a new object of our struct-type, gives it a type, sets a number and returns the object itself. Be aware, that the method can receive loads of arguments (args), but the actual number of arguments is determined by <em>n_args<\/em>.&nbsp;The&nbsp;<em>print<\/em>-method is called, when a Python-script calls \"print ( our_object )\", i.e. is expected to print some information about the object to screen.<\/p>\n<p>You will probably want to add \"helloObj\" to the list of QStrings, as well as to the list of global names of the module:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_map_elem_t<\/span><span class=\"w\"> <\/span><span class=\"n\">global_table<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR___name__<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_mymodule<\/span><span class=\"p\">)<\/span><span class=\"w\">  <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_hello<\/span><span class=\"p\">),<\/span><span class=\"w\">    <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_hello_obj<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_NEW_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_helloObj<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">)<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mymodule_helloObj_obj<\/span><span class=\"w\"> <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>If you want to add a method or two, create a C-function then add it to the local dictionary of the class and add the name of the function to the list of QStrings:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_increment<\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">self_in<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mymodule_hello_obj_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">self<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_OBJ_TO_PTR<\/span><span class=\"p\">(<\/span><span class=\"n\">self_in<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">self<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">hello_number<\/span><span class=\"w\"> <\/span><span class=\"o\">+=<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_const_none<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">MP_DEFINE_CONST_FUN_OBJ_1<\/span><span class=\"p\">(<\/span><span class=\"n\">mymodule_hello_increment_obj<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_increment<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">STATIC<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_rom_map_elem_t<\/span><span class=\"w\"> <\/span><span class=\"n\">mymodule_hello_locals_dict_table<\/span><span class=\"p\">[]<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_ROM_QSTR<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR_inc<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_ROM_PTR<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mymodule_hello_increment_obj<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">},<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"raising-exceptions\">Raising Exceptions<\/h3>\n<p>Raising Exceptions could be quite interesting from inside a C-module for Micropython. You might want to signal to Python, that some I\/O-operation did not work or some other error-state. You can use the&nbsp;<em>nlr_raise<\/em>-Makro for that.<\/p>\n<p>You can see&nbsp;<em>mp_raise_msg<\/em> for an example of the usage of that makro:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">NORETURN<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_raise_msg<\/span><span class=\"p\">(<\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_obj_type_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">exc_type<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">msg<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">nlr_raise<\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_new_exception<\/span><span class=\"p\">(<\/span><span class=\"n\">exc_type<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">nlr_raise<\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_new_exception_msg<\/span><span class=\"p\">(<\/span><span class=\"n\">exc_type<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">msg<\/span><span class=\"p\">));<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"conclusions\">Conclusions<\/h3>\n<p>This article depicted briefly how you can go and create your own modules for the Python interpreter Micropython. You should now be able to use the interface, and I hope I could shed some light on the back-stage part.<\/p>\n<h3 id=\"references\">References<\/h3>\n<p>[1]&nbsp;<a href=\"https:\/\/github.com\/naums\/micropython-dev-docs\/blob\/master\/adding-module.rst\">https:\/\/github.com\/naums\/micropython-dev-docs\/blob\/master\/adding-module.rst<\/a><br\/>\n[2]&nbsp;<a href=\"https:\/\/github.com\/micropython\/micropython\/blob\/master\/py\/obj.h\">https:\/\/github.com\/micropython\/micropython\/blob\/master\/py\/obj.h<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Builtin"}},{"@attributes":{"term":"C"}},{"@attributes":{"term":"Class"}},{"@attributes":{"term":"Compiler"}},{"@attributes":{"term":"Function"}},{"@attributes":{"term":"Micropython"}},{"@attributes":{"term":"Module"}},{"@attributes":{"term":"Python"}}]},{"title":"Porting Micropython to the Raspberry Pi - Part 2","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/porting-micropython-to-the-raspberry-pi-part-2.html","rel":"alternate"}},"published":"2017-07-11T10:08:00+02:00","updated":"2017-07-11T10:08:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-07-11:\/informatik\/porting-micropython-to-the-raspberry-pi-part-2.html","summary":"<p>In a previous post [1] I commented on how to port the Micropython Interpreter to the Rasperry Pi. There I went over the basics of porting Micropython to a new hardware and showed some ways on how to configure your port. This post builds upon that foundation and uses the \u2026<\/p>","content":"<p>In a previous post [1] I commented on how to port the Micropython Interpreter to the Rasperry Pi. There I went over the basics of porting Micropython to a new hardware and showed some ways on how to configure your port. This post builds upon that foundation and uses the Micropython which did run in principle, but ran into some nasty problems when executing code. Often I would receive failed assertions which could not fail.<\/p>\n<p>At first I (with the help of my colleague) tested basic statements of Python and watched the Raspberry Pi fail. Basic&nbsp;<em>print<\/em>-Statements with a fixed string, basic variable operations, later&nbsp;<em>if<\/em>,&nbsp;<em>while<\/em> and&nbsp;<em>for<\/em>. We did compile Micropython to talk to use really verbosely. It should output every last detail of what it does.<\/p>\n<h3 id=\"what-changed-from-last-time\">What changed from last time<\/h3>\n<p>But first I need to talk about what changed since the first post. I removed the neccessety to use&nbsp;<em>newlib<\/em> as external library and started using the libC-Implementation of Micropython. This implementation is not complete but complete enough to run the interpreter on a new hardware. Functions like&nbsp;<em>fopen<\/em> do not exist, but we don't need them anyways (until now).<\/p>\n<p>Also I build a new build-system. I incorporated description-files into my PiOS-project, which describe the specifications of the hardware to be built for. In the Makefile of the Raspberry Pi-port there is a variable&nbsp;<em>BOARD<\/em> which can be set to&nbsp;<em>rpi<\/em> or&nbsp;<em>qemu<\/em>. Yes, the same code can be compiled for QEMU, which is pretty great for testing and finding differences.<\/p>\n<h3 id=\"making-micropython-talk-to-us\">Making Micropython talk to us<\/h3>\n<p>There are two main ways of making Micropython talk a lot. The first one is settings the flag&nbsp;<em>mp_verbose_flag<\/em>&nbsp;at runtime to something greater than 2. I believe this flag will not be used in future (or something), it is used only once in the entirety of the code. This flag decides whether Micropython will print the Bytecode and a string-representation of the Bytecode or not.<\/p>\n<p>Then there are&nbsp;<em>DEBUG_printf<\/em>-makros inside the code. For example like this (from <a href=\"https:\/\/github.com\/micropython\/micropython\/blob\/master\/py\/bc.c#L38-L43\">bc.c<\/a>&nbsp;[2]):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#if 0<\/span><span class=\"c\"> \/\/ print debugging info<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"c\">#define DEBUG_PRINT (1)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#else \/\/ don't print debugging info<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define DEBUG_PRINT (0)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define DEBUG_printf(...) (void)0<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#endif<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This code disables by default loads of output inside the code-file. Many code-files of Micropython have statements like these on the top. I changed it per file to [3]:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#if MICROPY_DEBUG_VERBOSE <\/span><span class=\"c1\">\/\/ print debugging info<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define DEBUG_PRINT (1)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#else <\/span><span class=\"c1\">\/\/ don't print debugging info<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define DEBUG_PRINT (0)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define DEBUG_printf(...) (void)0<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#endif<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Then I can define the preprocessor constant <em>MICROPY_DEBUG_VERBOSE&nbsp;<\/em>in the ports&nbsp;<em>mpconfigport.h<\/em>-file. This will enable output of every last part of Micropython, i.e. also the Garbage-Collector.<\/p>\n<h3 id=\"what-is-wrong\">What is wrong?<\/h3>\n<p>So I tried several statements all seemed to work fine, except&nbsp;<em>for<\/em>,&nbsp;<em>while<\/em> and <em>if<\/em>-statements. When looking through the Bytecode I found JUMP-statements with wrong Labels, like for the following code:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">do_str<\/span><span class=\"p\">(<\/span><span class=\"s\">\"for i in range(10):<\/span><span class=\"se\">\\n<\/span><span class=\"s\">    print(i)\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_PARSE_FILE_INPUT<\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>I got the following Bytecode and String-Representation:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">File<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"n\">stdin<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">code<\/span><span class=\"w\"> <\/span><span class=\"n\">block<\/span><span class=\"w\"> <\/span><span class=\"err\">'<\/span><span class=\"o\">&lt;<\/span><span class=\"n\">module<\/span><span class=\"o\">&gt;<\/span><span class=\"err\">'<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">descriptor<\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"mf\">66f<\/span><span class=\"n\">b0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">bytecode<\/span><span class=\"w\"> <\/span><span class=\"mi\">@67040<\/span><span class=\"w\"> <\/span><span class=\"mi\">41<\/span><span class=\"w\"> <\/span><span class=\"n\">bytes<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Raw<\/span><span class=\"w\"> <\/span><span class=\"n\">bytecode<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">code_info_size<\/span><span class=\"o\">=<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">bytecode_size<\/span><span class=\"o\">=<\/span><span class=\"mi\">35<\/span><span class=\"p\">)<\/span><span class=\"o\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"mo\">03<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">06<\/span><span class=\"w\"> <\/span><span class=\"mi\">09<\/span><span class=\"w\"> <\/span><span class=\"mi\">10<\/span><span class=\"w\"> <\/span><span class=\"mi\">29<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"n\">ff<\/span><span class=\"w\"> <\/span><span class=\"mi\">80<\/span><span class=\"w\"> <\/span><span class=\"mi\">35<\/span><span class=\"w\"> <\/span><span class=\"mf\">0f<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"mi\">80<\/span><span class=\"w\"> <\/span><span class=\"mi\">30<\/span><span class=\"w\"> <\/span><span class=\"mi\">24<\/span><span class=\"w\"> <\/span><span class=\"mi\">82<\/span><span class=\"w\"> <\/span><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"n\">c<\/span><span class=\"w\"> <\/span><span class=\"mi\">81<\/span><span class=\"w\"> <\/span><span class=\"mf\">6f<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"n\">c<\/span><span class=\"w\"> <\/span><span class=\"mi\">82<\/span><span class=\"w\"> <\/span><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"mi\">64<\/span><span class=\"w\"> <\/span><span class=\"mo\">01<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"mi\">81<\/span><span class=\"w\"> <\/span><span class=\"n\">e9<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"mi\">30<\/span><span class=\"w\"> <\/span><span class=\"mi\">8<\/span><span class=\"n\">a<\/span><span class=\"w\"> <\/span><span class=\"n\">f0<\/span><span class=\"w\"> <\/span><span class=\"mi\">36<\/span><span class=\"w\"> <\/span><span class=\"n\">eb<\/span><span class=\"w\"> <\/span><span class=\"mf\">7f<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"mi\">11<\/span><span class=\"w\"> <\/span><span class=\"mi\">5<\/span><span class=\"n\">b<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">arg<\/span><span class=\"w\"> <\/span><span class=\"n\">names<\/span><span class=\"o\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">(<\/span><span class=\"n\">N_STATE<\/span><span class=\"w\"> <\/span><span class=\"mi\">3<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">(<\/span><span class=\"n\">N_EXC_STACK<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"n\">bc<\/span><span class=\"o\">=<\/span><span class=\"mi\">-1<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"o\">=<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"n\">bc<\/span><span class=\"o\">=<\/span><span class=\"mi\">8<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"o\">=<\/span><span class=\"mi\">2<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_SMALL_INT<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">01<\/span><span class=\"w\"> <\/span><span class=\"n\">JUMP<\/span><span class=\"w\"> <\/span><span class=\"mi\">4294938425<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">04<\/span><span class=\"w\"> <\/span><span class=\"n\">DUP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">05<\/span><span class=\"w\"> <\/span><span class=\"n\">STORE_NAME<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">08<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_NAME<\/span><span class=\"w\"> <\/span><span class=\"n\">print<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">11<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_NAME<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">14<\/span><span class=\"w\"> <\/span><span class=\"n\">CALL_FUNCTION<\/span><span class=\"w\"> <\/span><span class=\"n\">n<\/span><span class=\"o\">=<\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"n\">nkw<\/span><span class=\"o\">=<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">16<\/span><span class=\"w\"> <\/span><span class=\"n\">POP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">17<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_SMALL_INT<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">18<\/span><span class=\"w\"> <\/span><span class=\"n\">BINARY_OP<\/span><span class=\"w\"> <\/span><span class=\"mi\">18<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">19<\/span><span class=\"w\"> <\/span><span class=\"n\">DUP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">20<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_SMALL_INT<\/span><span class=\"w\"> <\/span><span class=\"mi\">10<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">21<\/span><span class=\"w\"> <\/span><span class=\"n\">BINARY_OP<\/span><span class=\"w\"> <\/span><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"n\">__lt__<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">22<\/span><span class=\"w\"> <\/span><span class=\"n\">POP_JUMP_IF_TRUE<\/span><span class=\"w\"> <\/span><span class=\"mi\">4<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"n\">POP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">26<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_NONE<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">27<\/span><span class=\"w\"> <\/span><span class=\"n\">RETURN_VALUE<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>For comparison this is the QEMU-output:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">File<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;<\/span><span class=\"n\">stdin<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">code<\/span><span class=\"w\"> <\/span><span class=\"n\">block<\/span><span class=\"w\"> <\/span><span class=\"err\">'<\/span><span class=\"o\">&lt;<\/span><span class=\"n\">module<\/span><span class=\"o\">&gt;<\/span><span class=\"err\">'<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">descriptor<\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"mi\">6<\/span><span class=\"n\">efa0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">bytecode<\/span><span class=\"w\"> <\/span><span class=\"mf\">@6f<\/span><span class=\"mo\">030<\/span><span class=\"w\"> <\/span><span class=\"mi\">41<\/span><span class=\"w\"> <\/span><span class=\"n\">bytes<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Raw<\/span><span class=\"w\"> <\/span><span class=\"n\">bytecode<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">code_info_size<\/span><span class=\"o\">=<\/span><span class=\"mi\">6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">bytecode_size<\/span><span class=\"o\">=<\/span><span class=\"mi\">35<\/span><span class=\"p\">)<\/span><span class=\"o\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"mo\">03<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">06<\/span><span class=\"w\"> <\/span><span class=\"mi\">09<\/span><span class=\"w\"> <\/span><span class=\"mi\">10<\/span><span class=\"w\"> <\/span><span class=\"mi\">29<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"n\">ff<\/span><span class=\"w\"> <\/span><span class=\"mi\">80<\/span><span class=\"w\"> <\/span><span class=\"mi\">35<\/span><span class=\"w\"> <\/span><span class=\"mf\">0f<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"mi\">80<\/span><span class=\"w\"> <\/span><span class=\"mi\">30<\/span><span class=\"w\"> <\/span><span class=\"mi\">24<\/span><span class=\"w\"> <\/span><span class=\"mi\">82<\/span><span class=\"w\"> <\/span><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"n\">c<\/span><span class=\"w\"> <\/span><span class=\"mi\">81<\/span><span class=\"w\"> <\/span><span class=\"mf\">6f<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"n\">c<\/span><span class=\"w\"> <\/span><span class=\"mi\">82<\/span><span class=\"w\"> <\/span><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"mi\">64<\/span><span class=\"w\"> <\/span><span class=\"mo\">01<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"mi\">81<\/span><span class=\"w\"> <\/span><span class=\"n\">e9<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"mi\">30<\/span><span class=\"w\"> <\/span><span class=\"mi\">8<\/span><span class=\"n\">a<\/span><span class=\"w\"> <\/span><span class=\"n\">f0<\/span><span class=\"w\"> <\/span><span class=\"mi\">36<\/span><span class=\"w\"> <\/span><span class=\"n\">eb<\/span><span class=\"w\"> <\/span><span class=\"mf\">7f<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"mi\">11<\/span><span class=\"w\"> <\/span><span class=\"mi\">5<\/span><span class=\"n\">b<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">arg<\/span><span class=\"w\"> <\/span><span class=\"n\">names<\/span><span class=\"o\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">(<\/span><span class=\"n\">N_STATE<\/span><span class=\"w\"> <\/span><span class=\"mi\">3<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">(<\/span><span class=\"n\">N_EXC_STACK<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"n\">bc<\/span><span class=\"o\">=<\/span><span class=\"mi\">-1<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"o\">=<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"n\">bc<\/span><span class=\"o\">=<\/span><span class=\"mi\">8<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"o\">=<\/span><span class=\"mi\">2<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">00<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_SMALL_INT<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">01<\/span><span class=\"w\"> <\/span><span class=\"n\">JUMP<\/span><span class=\"w\"> <\/span><span class=\"mi\">19<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">04<\/span><span class=\"w\"> <\/span><span class=\"n\">DUP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mo\">05<\/span><span class=\"w\"> <\/span><span class=\"n\">STORE_NAME<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">08<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_NAME<\/span><span class=\"w\"> <\/span><span class=\"n\">print<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">11<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_NAME<\/span><span class=\"w\"> <\/span><span class=\"n\">i<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">14<\/span><span class=\"w\"> <\/span><span class=\"n\">CALL_FUNCTION<\/span><span class=\"w\"> <\/span><span class=\"n\">n<\/span><span class=\"o\">=<\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"n\">nkw<\/span><span class=\"o\">=<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">16<\/span><span class=\"w\"> <\/span><span class=\"n\">POP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">17<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_SMALL_INT<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">18<\/span><span class=\"w\"> <\/span><span class=\"n\">BINARY_OP<\/span><span class=\"w\"> <\/span><span class=\"mi\">18<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">19<\/span><span class=\"w\"> <\/span><span class=\"n\">DUP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">20<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_SMALL_INT<\/span><span class=\"w\"> <\/span><span class=\"mi\">10<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">21<\/span><span class=\"w\"> <\/span><span class=\"n\">BINARY_OP<\/span><span class=\"w\"> <\/span><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"n\">__lt__<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">22<\/span><span class=\"w\"> <\/span><span class=\"n\">POP_JUMP_IF_TRUE<\/span><span class=\"w\"> <\/span><span class=\"mi\">4<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">25<\/span><span class=\"w\"> <\/span><span class=\"n\">POP_TOP<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">26<\/span><span class=\"w\"> <\/span><span class=\"n\">LOAD_CONST_NONE<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">27<\/span><span class=\"w\"> <\/span><span class=\"n\">RETURN_VALUE<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This was the moment I went to the Github-Issue-Tracker of Micropython and looked for help [4]. As Mr. George pointed out the errors might be due to the inability of the ARM1176jzf-s processor to load unaligned data. Apparently the ARMv5 processors where completely unable to load unaligned data, that is data which is not aligned with the word-size of the processor, i.e. with 32-bit words aligned to 4-byte addresses (the address does not end with 0b00). In ARMv6 ARM added an extention which allowed loading and storing unaligned data. The ARM1176jzf-s specifically has a system coprocessor which could be set to allow unaligned accesses [5].<\/p>\n<p>Setting the U-flag (22nd Bit) c1-control register of the C15 coprocessor allows us to access unaligned data without the processor throwing an exception to the kernel to resolve the issue. So this is the code, which I added to my bootup-assembly with the help of this RaspberryPi-Forum post [7].<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"o\">\/\/\/<\/span><span class=\"w\"> <\/span><span class=\"nb\">load<\/span><span class=\"w\"> <\/span><span class=\"n\">C15<\/span><span class=\"w\"> <\/span><span class=\"n\">control<\/span><span class=\"w\"> <\/span><span class=\"n\">register<\/span><span class=\"w\"> <\/span><span class=\"n\">c1<\/span><span class=\"o\">-<\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"mi\">0<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">c1<\/span><span class=\"w\"> <\/span><span class=\"n\">Control<\/span><span class=\"w\"> <\/span><span class=\"n\">Register<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"n\">into<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">mrc<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mh\">0x00400000<\/span><span class=\"w\">     <\/span><span class=\"o\">\/\/\/<\/span><span class=\"w\"> <\/span><span class=\"n\">set<\/span><span class=\"w\"> <\/span><span class=\"n\">bit<\/span><span class=\"w\"> <\/span><span class=\"mi\">22<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">U<\/span><span class=\"o\">-<\/span><span class=\"n\">bit<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">orr<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">mcr<\/span><span class=\"w\"> <\/span><span class=\"n\">p15<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">c0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"further-reading\">Further Reading<\/h3>\n<p>I found the article under [8] especially helpful in understanding the problem and finding some solutions.<\/p>\n<p>Possible solutions which I tried before, was to resolve the issue with the wrongly accessed JUMP-label by using a function, which the compiler cannot optimize (<em>__attribute__((optimize('0')))<\/em>) so the two Byte-loads cannot be optimized to a single 16-bit load. This worked well for outputting the Bytecode as strings, but the code crashed before execution due to another unaligned (I guess). The assertion&nbsp;*rc-&gt;kind == MP_BYTECODE&nbsp;* failed, which prevented Micropython from executing the code.<\/p>\n<h3 id=\"references\">References<\/h3>\n<p>[1]&nbsp;<a href=\"https:\/\/www.stefannaumann.de\/en\/2017\/05\/porting-micropython-to-raspberry-pi\/\">https:\/\/www.stefannaumann.de\/en\/2017\/05\/porting-micropython-to-raspberry-pi\/<\/a><br\/>\n[2]&nbsp;<a href=\"https:\/\/github.com\/micropython\/micropython\/blob\/master\/py\/bc.c#L38-L43\">https:\/\/github.com\/micropython\/micropython\/blob\/master\/py\/bc.c#L38-L43<\/a><br\/>\n[3] <a href=\"https:\/\/github.com\/tuc-osg\/micropython\/blob\/master\/py\/bc.c#L38-L43\">https:\/\/github.com\/tuc-osg\/micropython\/blob\/master\/py\/bc.c#L38-L43<br\/>\n<\/a>[4] <a href=\"https:\/\/github.com\/micropython\/micropython\/issues\/3201\">https:\/\/github.com\/micropython\/micropython\/issues\/3201<br\/>\n<\/a>[5]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch03s02s01.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/ch03s02s01.html<\/a><br\/>\n[6]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/Bgbciiaf.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0301h\/Bgbciiaf.html<\/a><br\/>\n[7]&nbsp;<a href=\"https:\/\/www.raspberrypi.org\/forums\/viewtopic.php?f=72&amp;t=126891\">https:\/\/www.raspberrypi.org\/forums\/viewtopic.php?f=72&amp;t=126891<\/a><br\/>\n[8]&nbsp;<a href=\"http:\/\/antirez.com\/news\/111\">http:\/\/antirez.com\/news\/111<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Bare Metal"}},{"@attributes":{"term":"Bytecode"}},{"@attributes":{"term":"Computer Science"}},{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Micropython"}},{"@attributes":{"term":"PilotOS"}},{"@attributes":{"term":"PylotOS"}},{"@attributes":{"term":"Python"}},{"@attributes":{"term":"Raspberry Pi"}}]},{"title":"PiOS: ARM Timer and Interrupts","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/pios-arm-timer-and-interrupts.html","rel":"alternate"}},"published":"2017-05-28T19:40:00+02:00","updated":"2017-05-28T19:40:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-05-28:\/informatik\/pios-arm-timer-and-interrupts.html","summary":"<p>For quite some time I've been working on a prototypic operating system, PiOS (previously PilotOS) [1]. I've been writing articles earlier about processes [2][3] and I want to discuss the current state here. Additional to a rewrite of most of the code, so removing the assembler-code and rewriting its \u2026<\/p>","content":"<p>For quite some time I've been working on a prototypic operating system, PiOS (previously PilotOS) [1]. I've been writing articles earlier about processes [2][3] and I want to discuss the current state here. Additional to a rewrite of most of the code, so removing the assembler-code and rewriting its functionality in C, I've also created some drivers for i2c and a LCD character display. The latter two I cannot test at the moment, so these serve as untested prove of concept-drivers. Today I have implemented the ARM Timer [4, pg. 196] and have received my first interrupts.<\/p>\n<p>At first I normally add a map for the registers of the peripheral, which are bound to an address in the memory, so I have a data structure with names (normally a&nbsp;<em>struct<\/em>) to address the registers (see Memory Mapped I\/O). The ARM-timer has nine 32-Bit registers:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_pios_arm_timer_t<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">load<\/span><span class=\"p\">;<\/span><span class=\"w\">          <\/span><span class=\"c1\">\/\/\/&lt; load a specific value into the counter, after counted-down an IRQ occurs<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">value<\/span><span class=\"p\">;<\/span><span class=\"w\">         <\/span><span class=\"c1\">\/\/\/&lt; a value, counted down. On 0 IRQ is set and the value is reloaded from reload-register<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">control<\/span><span class=\"p\">;<\/span><span class=\"w\">       <\/span><span class=\"c1\">\/\/\/&lt; control register, which allows for setting some settings<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">irqack<\/span><span class=\"p\">;<\/span><span class=\"w\">        <\/span><span class=\"c1\">\/\/\/&lt; write only for clearing the IRQ-line<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">irqraw<\/span><span class=\"p\">;<\/span><span class=\"w\">        <\/span><span class=\"c1\">\/\/\/&lt; is an interrupt pending? (i.e. LSB is set to 1)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">irqmasked<\/span><span class=\"p\">;<\/span><span class=\"w\">     <\/span><span class=\"c1\">\/\/\/&lt; is the IRQ pending bit set and the interrupt enable bit?<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">reload<\/span><span class=\"p\">;<\/span><span class=\"w\">        <\/span><span class=\"c1\">\/\/\/&lt; copy of load, but writing will not trigger an overwrite of value, just when value reaches 0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">prescale<\/span><span class=\"p\">;<\/span><span class=\"w\">      <\/span><span class=\"c1\">\/\/\/&lt; setting a prescaler for the timer - LSB 10 Bits (timer_clock = apb_clock\/(pre_divider+1))<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">freerunning<\/span><span class=\"p\">;<\/span><span class=\"w\">   <\/span><span class=\"c1\">\/\/\/&lt; a free running value (has its own prescaler in control-register)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"n\">pios_arm_timer_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>This timer is quite simple. It has a free running register, i.e. it will be increased with every timer-tick (note the prescaler!). Also the timer can be used as an alarm-clock. One can save a value into the register&nbsp;<em>load<\/em>, which will be decremented on every timer-tick, until it reaches zero. When zero an interrupt will be triggered and the value, last written to&nbsp;<em>load<\/em> (or&nbsp;<em>reload<\/em>) will be copied to&nbsp;<em>value<\/em> once again.<\/p>\n<p>The settings of the timer can be controlled via the&nbsp;<em>control<\/em>-Register. The semantics of the bits are demonstrated in the BCM2835 peripheral manuel. The bits can be set as C-constants:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#define PIOS_ARM_TIMER_32BIT 2<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_1 (0 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_16 (1 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_256 (2 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_UNDEF (3 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_IRQ_ENABLE (1 &lt;&lt; 5)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_ENABLE (1 &lt;&lt; 7)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_HALT_IN_DEBUG (1 &lt;&lt; 8)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_FREERUNNING_ENABLE (1 &lt;&lt; 9)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_FREERUNNING_PRESCALER(a) ((a&amp;0xff) &lt;&lt; 16)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The&nbsp;<em>freerunning<\/em>-Register has a different prescale-value than the normal alarm-clock mode of the Timer, so it can be viewed more or less independently. Note that the according Macro takes an 8-Bit value and shifts it by 16 places to the left - a better solution would be nice and will maybe come some when in the future(tm).<\/p>\n<h2 id=\"understanding-how-does-a-timer-work\">Understanding&nbsp;how does a&nbsp;Timer work<\/h2>\n<p>In principle a timer uses an oscillator, for example an Quarz-oscillator. This crystal is motivated to vibrate slightly by a voltage (see piezo-electrical effect). This vibration leads to a charge generating between the two ends of the crystal. It vibrates more or less at a constant and exact frequency and generates therefore a periodic signal, which is ideally already a square-wave. But to be sure one should send it through something like a Schmidt-trigger, wo generate a good square-wave. The Schmidt-trigger can also generate &nbsp;voltage-levels so that the digital hardware will recognize them correctly as HIGH or LOW-levels.<\/p>\n<p>The timer or counter itself is a series of Flip-Flops (i.e. 1 Bit-memory). One can use T-Flip-Flops (Trigger-Flip-Flops), which will change there value when the input-signal has the logical level of 1. These memory units are connected so that, when the least significant bit (LSB) changes from 1 to 0, the next more significant unit changes its value. This can be done by using the output of the LSB-Flip-Flop as input for the clock-signal of the next higher FF. Flip-Flops normally react to an edge in the clock-signal, not to HIGH\/LOW-levels.<\/p>\n<h3 id=\"the-prescaler\">The&nbsp;Prescaler<\/h3>\n<p>A prescaler or predivider divides a faster voltage-signal, for example as it is output by the Schmidt-trigger, so it reaches a slower frequency. For division by a factor of two, four, eight, etc. one can use Flip-Flops, which are put before the counter. The output of this prescale-circuit is then used as the input of the counter. The prescaler-Flip-Flops in a way \"stretch\" the HIGH and LOW-level-phases of the input-signal for the counter.<\/p>\n<h2 id=\"interrupts_1\">Interrupts<\/h2>\n<p>The ARM-processor of the Raspberry Pi can handle exactly eight interrupt sources. These Interrupts do not have to be generated by external hardware, but can also be generated by the CPU itself. The processor needs to know what has to be done, when an interrupt occurs. Therefore a so called Interrupt Table is put into the memory, which denotes what has to be done, or what address has to be put into the Programm Counter (<em>pc<\/em>) when a specific interrupt occurs. This table is put into the physical address 0x0000 0000, i.e. exactly at the Null-point of the memory and is 8 by 8 Bytes big (2*4 Byte per interrupt-source). As far as I know the interrupt table&nbsp;<strong>has<\/strong> to be set in software and cannot be generated at Compile-time, like with the AVR-processors. The following code (from [5]) works for that:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">start<\/span><span class=\"p\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_reset_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_undefined_instruction_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_software_interrupt_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_prefetch_abort_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_data_abort_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_unused_handler_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_interrupt_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_fast_interrupt_vector_h<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">_reset_h<\/span><span class=\"p\">:<\/span><span class=\"w\">                           <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">_reset_<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_undefined_instruction_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">    <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">undef_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_software_interrupt_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">       <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">swi_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_prefetch_abort_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">           <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">abort_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_data_abort_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">               <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">abort_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_unused_handler_h<\/span><span class=\"p\">:<\/span><span class=\"w\">                  <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">_reset_<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_interrupt_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">                <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">irq_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_fast_interrupt_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">           <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">fiq_vector<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">_reset_<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\">     <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"c1\">#0x8000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\">     <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"c1\">#0x0000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r0<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><span class=\"w\">    <\/span><span class=\"o\">\/**<\/span><span class=\"w\"> <\/span><span class=\"nb\">load<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"n\">Byte<\/span><span class=\"w\"> <\/span><span class=\"n\">worth<\/span><span class=\"w\"> <\/span><span class=\"n\">of<\/span><span class=\"w\"> <\/span><span class=\"n\">data<\/span><span class=\"w\"> <\/span><span class=\"o\">**\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">stmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r1<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><span class=\"w\">    <\/span><span class=\"o\">\/**<\/span><span class=\"w\"> <\/span><span class=\"n\">store<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"n\">Byte<\/span><span class=\"w\"> <\/span><span class=\"o\">**\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r0<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">stmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r1<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>In a first attempt I created the following empty interrupt service routines, which uses the UART for a simple output and hung in an endless loop:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"UNDEF\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">undef_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"UNDEF :( <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"IRQ\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">irq_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\" -&gt; ! IRQ :) <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"FIQ\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">fiq_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"FIQ :( <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"SWI\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">swi_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"SWI :( <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"ABORT\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">abort_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"ABORT :(<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"enable-interrupts\">Enable Interrupts<\/h3>\n<p>So our processor knows what to do, when an interrupt arrives. But it will not do anything, because we need to enable interrupts in our processor. So we can disable interrupts, i.e. advice our processor to ignore interrupts (as well as fast interrupts). This is default, when the Raspberry Pi is switched on. [7] states, that 0x80 is the bit for disabling&nbsp;interrupts in our processor. So we can enable the interrupt handling by clearing the value of that bit.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">pios_irq_enable<\/span><span class=\"o\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mrs<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bic<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mh\">0x80<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">msr<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr_c<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Note, that the Programm Status Register (<em>cpsr<\/em>) can only be modified by specific instructions (<em>mrs, msr<\/em>). These instructions are only allowed in specific privilege settings of the processor and will lead to an interrupt in the user-mode. User-programs should not be allowed to edit the state-register of our processor and are therefore not allowed to change the mode.<\/p>\n<h3 id=\"interrupt-controller\">Interrupt-Controller<\/h3>\n<p>The&nbsp;ARM1176jzf-s, which is built into the Raspberry Pi, uses&nbsp;an additional trick. The ARM-core itself can only handle 8 interrupt sources. But interrupts can come from several external devices and may have different reasons. To be able to enable or disable interrupts more precisely the Pi has an interrupt controller, which works together with the ARM-code.<\/p>\n<p>According to the manual [4, pg. 109] the controller can be found at 0x2000 B2000 (note: the address in the manual is the one which is used on the ARM-bus, not the one used by the ARM-code, i.e. our software). The correct registers for enabling or disabling interrupt sources are located here. We want to enable the timer as interrupt source, so we write the correct value into the Base Interrupt Enable register.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/*(0x2000B218) = (1&lt;&lt;0)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">RPI_GetIrqController<\/span><span class=\"p\">()<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">Enable_Basic_IRQs<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RPI_BASIC_ARM_TIMER_IRQ<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"set-up-the-alarm-clock_1\">Set-up&nbsp;the Alarm Clock<\/h2>\n<p>Before the timer-interrupt is enabled we should set-up the alarm clock. We want to set the correct start value into the&nbsp;<em>load<\/em>-Register and activate the Timer with the correct value for us (32-Bit mode, with enabled interrupts and enabled timer):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ pios_arm_timer-&gt;load = load;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">pios_arm_timer_setLoad<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x2000<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * if ( !(prescaler == PIOS_ARM_TIMER_PRESCALE_1 || prescaler == PIOS_ARM_TIMER_PRESCALE_16 <\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *     || prescaler == PIOS_ARM_TIMER_PRESCALE_256 || prescaler == PIOS_ARM_TIMER_PRESCALE_UNDEF) )<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   {<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *       prescaler = PIOS_ARM_TIMER_PRESCALE_256;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   }<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   uint32_t val = PIOS_ARM_TIMER_32BIT | prescaler | (irq ? PIOS_ARM_TIMER_IRQ_ENABLE : 0) | PIOS_ARM_TIMER_FREERUNNING_ENABLE | (enable ? PIOS_ARM_TIMER_ENABLE:0);<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   pios_arm_timer-&gt;control = val;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">**\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">pios_arm_timer_init<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">PIOS_ARM_TIMER_PRESCALE_256<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Nun&nbsp;we receive interrupts from our timer.<\/p>\n<p>[1]&nbsp;<a href=\"https:\/\/github.com\/naums\/PiOS\">https:\/\/github.com\/naums\/PiOS<br\/>\n<\/a>[2]&nbsp;<a href=\"https:\/\/www.stefannaumann.de\/en\/2016\/05\/pilotos-processes\/\">https:\/\/www.stefannaumann.de\/en\/2016\/05\/pilotos-processes\/<\/a><br\/>\n[3]&nbsp;<a href=\"https:\/\/www.stefannaumann.de\/en\/2016\/05\/pilotos-processes-2-process-states-and-mutual-exclusion\/\">https:\/\/www.stefannaumann.de\/en\/2016\/05\/pilotos-processes-2-process-states-and-mutual-exclusion\/<\/a><br\/>\n[4]&nbsp;<a href=\"https:\/\/www.raspberrypi.org\/documentation\/hardware\/raspberrypi\/bcm2835\/BCM2835-ARM-Peripherals.pdf\">https:\/\/www.raspberrypi.org\/documentation\/hardware\/raspberrypi\/bcm2835\/BCM2835-ARM-Peripherals.pdf<\/a><br\/>\n[5]&nbsp;<a href=\"http:\/\/www.valvers.com\/open-software\/raspberry-pi\/step04-bare-metal-programming-in-c-pt4\/\">http:\/\/www.valvers.com\/open-software\/raspberry-pi\/step04-bare-metal-programming-in-c-pt4\/<\/a><br\/>\n[6]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/ch02s09s01.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/ch02s09s01.html<\/a><br\/>\n[7]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/I2837.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/I2837.html<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"ARM"}},{"@attributes":{"term":"Embedded"}},{"@attributes":{"term":"LowLevel"}},{"@attributes":{"term":"Operating System"}},{"@attributes":{"term":"PilotOS"}},{"@attributes":{"term":"PiOS"}},{"@attributes":{"term":"Prototype"}},{"@attributes":{"term":"Raspberry Pi"}},{"@attributes":{"term":"Timer"}}]},{"title":"PiOS: ARM Timer und Interrupts","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/pios-arm-timer-and-interrupts-de.html","rel":"alternate"}},"published":"2017-05-28T19:10:00+02:00","updated":"2017-05-28T19:10:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-05-28:\/informatik\/pios-arm-timer-and-interrupts-de.html","summary":"<p>Seit einiger Zeit arbeite ich an einem prototypischem Betriebssystem, PiOS (\"fr&uuml;her\" PilotOS) [1]. Ich habe fr&uuml;her schon einige Artikel &uuml;ber Prozesse [2][3] geschrieben und will nun hier den aktuellen Stand diskutieren. Neben einem Rewrite des Codes, also entfernen quasi aller alten Assembler-Sourcen und Neuschreiben der Funktionalit&auml;t in C, sind \u2026<\/p>","content":"<p>Seit einiger Zeit arbeite ich an einem prototypischem Betriebssystem, PiOS (\"fr&uuml;her\" PilotOS) [1]. Ich habe fr&uuml;her schon einige Artikel &uuml;ber Prozesse [2][3] geschrieben und will nun hier den aktuellen Stand diskutieren. Neben einem Rewrite des Codes, also entfernen quasi aller alten Assembler-Sourcen und Neuschreiben der Funktionalit&auml;t in C, sind auch Treiber entstanden f&uuml;r i2c und einem LCD character display, die aktuell aufgrund fehlender Testm&ouml;glichkeiten lediglich Versuchsballons sind. Weiter habe ich heute den ARM Timer [4, S. 196 ff] implementiert und meine ersten Interrupts erhalten.<\/p>\n<p>Zun&auml;chst lege ich i.d.R. eine Map an f&uuml;r die Register, die im Speicheraddressraum eingebunden sind, sodass ich eine benannte Datenstruktur (i.d.R. ein&nbsp;<em>struct<\/em>) habe, welches ich benutzen kann um die Register der Peripherie anzusprechen (Stichwort: Memory Mapped I\/O). Der ARM-Timer verf&uuml;gt &uuml;ber 9 32-Bit Register:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">_pios_arm_timer_t<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">load<\/span><span class=\"p\">;<\/span><span class=\"w\">          <\/span><span class=\"c1\">\/\/\/&lt; load a specific value into the counter, after counted-down an IRQ occurs<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">value<\/span><span class=\"p\">;<\/span><span class=\"w\">         <\/span><span class=\"c1\">\/\/\/&lt; a value, counted down. On 0 IRQ is set and the value is reloaded from reload-register<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">control<\/span><span class=\"p\">;<\/span><span class=\"w\">       <\/span><span class=\"c1\">\/\/\/&lt; control register, which allows for setting some settings<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">irqack<\/span><span class=\"p\">;<\/span><span class=\"w\">        <\/span><span class=\"c1\">\/\/\/&lt; write only for clearing the IRQ-line<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">irqraw<\/span><span class=\"p\">;<\/span><span class=\"w\">        <\/span><span class=\"c1\">\/\/\/&lt; is an interrupt pending? (i.e. LSB is set to 1)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">irqmasked<\/span><span class=\"p\">;<\/span><span class=\"w\">     <\/span><span class=\"c1\">\/\/\/&lt; is the IRQ pending bit set and the interrupt enable bit?<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">reload<\/span><span class=\"p\">;<\/span><span class=\"w\">        <\/span><span class=\"c1\">\/\/\/&lt; copy of load, but writing will not trigger an overwrite of value, just when value reaches 0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">prescale<\/span><span class=\"p\">;<\/span><span class=\"w\">      <\/span><span class=\"c1\">\/\/\/&lt; setting a prescaler for the timer - LSB 10 Bits (timer_clock = apb_clock\/(pre_divider+1))<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">uint32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">freerunning<\/span><span class=\"p\">;<\/span><span class=\"w\">   <\/span><span class=\"c1\">\/\/\/&lt; a free running value (has its own prescaler in control-register)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">typedef<\/span><span class=\"w\"> <\/span><span class=\"n\">pios_arm_timer_t<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Der Timer ist recht einfach. Er hat ein Register, welches freilaufend ist, d.h. bei jedem Timer-Tick (beachte Prescaler!) hochgez&auml;hlt wird. Au&szlig;erdem besitzt der Timer &uuml;ber eine Art Wecker-Funktion. Ein Wert kann im Register&nbsp;<em>load<\/em> eingespeichert werden, welcher dekrementiert wird bei jedem Timer-Tick, solange bis das Register den Wert 0 erreicht. Ist 0 erreicht, wird der eingespeicherte Wert erneut eingetragen und eine Interrupt-Leitung gesetzt.<\/p>\n<p>Die Einstellungen des Timers sind komplett &uuml;ber das&nbsp;<em>control<\/em>-Register m&ouml;glich. Die Bedeutung der entsprechenden Bitstellen ist im BCM2835-Peripherie-Handbuch angegeben. Die Bits sind hier als C-Pr&auml;prozessor-Konstanten angegeben:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#define PIOS_ARM_TIMER_32BIT 2<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_1 (0 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_16 (1 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_256 (2 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_PRESCALE_UNDEF (3 &lt;&lt; 2)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_IRQ_ENABLE (1 &lt;&lt; 5)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_ENABLE (1 &lt;&lt; 7)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_HALT_IN_DEBUG (1 &lt;&lt; 8)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_FREERUNNING_ENABLE (1 &lt;&lt; 9)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#define PIOS_ARM_TIMER_FREERUNNING_PRESCALER(a) ((a&amp;0xff) &lt;&lt; 16)<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Das&nbsp;<em>freerunning<\/em>-Register hat einen eigenen Prescaler, sodass das Register unabh&auml;ngig vom \"Wecker\" betrachtet werden kann. Beachte, dass die Konstante dazu einen 8-Bit-Wert annimmt und um 16 Bits nach links schiebt - eine bessere M&ouml;glichkeit w&auml;re sch&ouml;n und kommt vielleicht irgendwann(tm).<\/p>\n<h2 id=\"funktionsweise-eines-timers\">Funktionsweise eines Timers<\/h2>\n<p>Ein Timer funktioniert prinzipiell so, dass im Chip ein Oszillator verbaut ist, bspw. ein Quarz-Oszillator. Dieser Quarzkristall wird durch Spannung angeregt sich zu verformen (siehe Piezo-elektrischer Effekt). Diese Verformung f&uuml;hrt dazu, dass sich eine Ladung des Quarzes ergibt. Der Kristall schwingt gewisserma&szlig;en in einer mehr oder weniger genauen Frequenz und erzeugt somit ein periodisches Signal, im Idealfall bereits ein Rechteckssignal, aber zur Sicherheit kann das Signal durch einen Schmidt-Trigger zum Rechteck gemacht werden. Au&szlig;erdem kann der Schmidt-Trigger die Spannungspegel so regeln, dass die Spannungen durch die digitale Hardware erkannt werden.<\/p>\n<p>Der eigentliche Timer oder Z&auml;hler besteht aus einer Reihe von Flip-Flops (also 1 Bit-Speicherbausteinen). Vorstellbar sind bspw. T-Flip-Flops (Trigger-Flip-Flops), die bei einer Eingabe des logischen Wertes 1 ihren Wert wechseln. Die Speicherbausteine sind so verschaltet, dass beim Schalten des ersten (Least Significant Bit) von 1 auf 0, der n&auml;chst h&ouml;here umschaltet, etc. bspw. indem die Ausgabe des LSB-Flip-Flops als Clock-Leitung genutzt wird. Flip-Flops reagieren i.d.R. auf eine Flanke, nicht auf einen (HIGH\/LOW)-Pegel.<\/p>\n<h3 id=\"der-prescaler\">Der&nbsp;Prescaler<\/h3>\n<p>Ein Prescaler, oder auch Vorteiler, teilt die schnelleren Spannungswechsel, die vom Schmidt-Trigger erzeugt werden, mehrfach vor, sodass eine langsamere Frequenz entsteht. F&uuml;r Teilungsfaktoren um den Faktor zwei werden wiederum Flip-Flops benutzt, die vor den eigentlichen Z&auml;hler geschaltet werden. Die Ausgabe der Vorteilerschaltung wird an die Eingabe des Z&auml;hlers geschaltet. Die Vorteiler-Flip-Flops strecken somit die LOW bzw. HIGH-Phasen des Eingangssignals f&uuml;r den Z&auml;hler.<\/p>\n<h2 id=\"interrupts_1\">Interrupts<\/h2>\n<p>Der ARM-Prozessor des Raspberry Pi kann&nbsp;genau acht Interrupt-Quellen unterscheiden. Dabei sind nicht alle Quellen tats&auml;chlich externe Hardware, sondern Interrupts k&ouml;nnen auch vom Prozessor selbst erzeugt werden. Damit der Prozessor wei&szlig;, was zu tun ist, wenn ein Interrupt auftritt, gibt es im Speicher eine so genannte Interrupt Tabelle, die angibt, wo der Prozessor hinspringen muss (bzw. welche Befehle auszuf&uuml;hren sind), wenn ein bestimmter Interupt auftritt. Diese Tabelle liegt beim Raspberry Pi an der physischen Adresse 0x0000 0000, d.h. genau am Nullpunkt und ist 8 mal 8 Byte gro&szlig; (2 * 4 Byte pro Interrupt-Quelle). Die Tabelle&nbsp;<strong>muss<\/strong> in Software gesetzt werden, sie kann soweit ich wei&szlig; nicht zur Compilezeit angelegt werden, wie bei den AVR-Prozessoren. Der folgende Code (von [5]) funktioniert daf&uuml;r:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">start<\/span><span class=\"p\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_reset_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_undefined_instruction_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_software_interrupt_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_prefetch_abort_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_data_abort_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_unused_handler_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_interrupt_vector_h<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">_fast_interrupt_vector_h<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">_reset_h<\/span><span class=\"p\">:<\/span><span class=\"w\">                           <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">_reset_<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_undefined_instruction_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">    <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">undef_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_software_interrupt_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">       <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">swi_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_prefetch_abort_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">           <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">abort_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_data_abort_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">               <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">abort_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_unused_handler_h<\/span><span class=\"p\">:<\/span><span class=\"w\">                  <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">_reset_<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_interrupt_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">                <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">irq_vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">_fast_interrupt_vector_h<\/span><span class=\"p\">:<\/span><span class=\"w\">           <\/span><span class=\"o\">.<\/span><span class=\"n\">word<\/span><span class=\"w\">   <\/span><span class=\"n\">fiq_vector<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"n\">_reset_<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\">     <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"c1\">#0x8000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\">     <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"c1\">#0x0000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r0<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><span class=\"w\">    <\/span><span class=\"o\">\/**<\/span><span class=\"w\"> <\/span><span class=\"nb\">load<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"n\">Byte<\/span><span class=\"w\"> <\/span><span class=\"n\">worth<\/span><span class=\"w\"> <\/span><span class=\"n\">of<\/span><span class=\"w\"> <\/span><span class=\"n\">data<\/span><span class=\"w\"> <\/span><span class=\"o\">**\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">stmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r1<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><span class=\"w\">    <\/span><span class=\"o\">\/**<\/span><span class=\"w\"> <\/span><span class=\"n\">store<\/span><span class=\"w\"> <\/span><span class=\"mi\">32<\/span><span class=\"w\"> <\/span><span class=\"n\">Byte<\/span><span class=\"w\"> <\/span><span class=\"o\">**\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r0<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">stmia<\/span><span class=\"w\">   <\/span><span class=\"n\">r1<\/span><span class=\"o\">!<\/span><span class=\"p\">,{<\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r8<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r9<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>In der ersten N&auml;herung lege ich mir folgende Interrupt-Service-Routinen an, die eine Ausgabe &uuml;ber UART t&auml;tigen und dann in einer Endlosschleife h&auml;ngen bleiben:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"UNDEF\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">undef_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"UNDEF :( <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"IRQ\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">irq_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\" -&gt; ! IRQ :) <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"FIQ\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">fiq_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"FIQ :( <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"SWI\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">swi_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"SWI :( <\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">__attribute__<\/span><span class=\"p\">((<\/span><span class=\"n\">interrupt<\/span><span class=\"p\">(<\/span><span class=\"s\">\"ABORT\"<\/span><span class=\"p\">)))<\/span><span class=\"w\"> <\/span><span class=\"n\">abort_vector<\/span><span class=\"p\">(<\/span><span class=\"kt\">void<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pios_uart_puts<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"s\">\"ABORT :(<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"cm\">\/* Do Nothing! *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h3 id=\"interrupts-anschalten\">Interrupts anschalten<\/h3>\n<p>Nun wei&szlig; also mein Prozessor was zu tun ist, wenn ein Interrupt kommt. Aber er wird noch nichts machen, weil die Interrupts im Prozessor noch angeschalten werden m&uuml;ssen. D.h. wir k&ouml;nnen unseren Prozessor anweisen externe Interrupt (wie auch Fast Interrupts) zu ignorieren. Das ist der Standardzustand, wenn der Raspberry Pi angeschalten wird. [7] gibt an, dass das IRQ-disable-Bit mit 0x80 angesprochen werden kann. Also aktivieren wir die Interruptbehandlung, indem wir das Bit auf 0 setzen (clear):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">pios_irq_enable<\/span><span class=\"o\">:<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mrs<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bic<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mh\">0x80<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">msr<\/span><span class=\"w\"> <\/span><span class=\"n\">cpsr_c<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"o\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Beachte, dass das Programm status register (<em>cpsr<\/em>) nur&nbsp;durch bestimmte Befehle bearbeitet werden kann (<em>mrs<\/em>, <em>msr<\/em>). Diese Befehle sind nur in bestimmten Rechteeinstellungen des Prozessors erlaubt und f&uuml;hren bspw. im User-Modus des Prozessors zu einem Interrupts. Das soll sicherstellen, dass Nutzerprogramme nicht in das Statusregister schreiben k&ouml;nnen und den Modus wechseln k&ouml;nnen.<\/p>\n<h3 id=\"interrupt-controller\">Interrupt-Controller<\/h3>\n<p>Der ARM1176jzf-s, der im Raspberry Pi verbaut ist, hat aber noch einen weiteren Trick im &Auml;rmel. Richtig ist, dass der ARM-Kern nur 8 Interrupt-Quellen behandeln kann. Dennoch kann ein Interrupt durch mehrere (externe) Ger&auml;te erzeugt werden oder verschiedene Gr&uuml;nde haben. Um pr&auml;ziser Interrupts ein- bzw. ausschalten zu k&ouml;nnen, hat der Pi einen Interrupt-Controller, der zusammen mit dem ARM-Kern arbeiten soll.<\/p>\n<p>Laut Handbuch [4, S.&nbsp;109 ff] ist der Controller unter der Adresse 0x2000 B200 zu erreichen (Beachte: die angegebene Adresse im Handbuch ist die, die &uuml;ber den ARM-Bus geht, nicht aber die Adresse, die vom ARM-Kern aus sichtbar ist). Hier sind bestimmte Register daf&uuml;r zust&auml;ndig Interruptquellen ein- bzw. auszuschalten. Wir wollen hier den Timer aktivieren, also schreiben wir den passenden Wert in das&nbsp;Base Interrupt enable register:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/*(0x2000B218) = (1&lt;&lt;0)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">RPI_GetIrqController<\/span><span class=\"p\">()<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">Enable_Basic_IRQs<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RPI_BASIC_ARM_TIMER_IRQ<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<h2 id=\"den-wecker-stellen_1\">Den Wecker stellen<\/h2>\n<p>Der Timer&nbsp;sollte zuvor gestellt werden. Dazu schreiben wir einen gew&uuml;nschten Startwert in das&nbsp;<em>load<\/em>-Register und aktivieren den Timer mit den f&uuml;r uns passenden Werten (32-Bit Modus, mit aktivierten Interrupts und angeschaltetem Timer):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"c1\">\/\/ pios_arm_timer-&gt;load = load;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">pios_arm_timer_setLoad<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x2000<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * if ( !(prescaler == PIOS_ARM_TIMER_PRESCALE_1 || prescaler == PIOS_ARM_TIMER_PRESCALE_16 <\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *     || prescaler == PIOS_ARM_TIMER_PRESCALE_256 || prescaler == PIOS_ARM_TIMER_PRESCALE_UNDEF) )<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   {<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *       prescaler = PIOS_ARM_TIMER_PRESCALE_256;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   }<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   uint32_t val = PIOS_ARM_TIMER_32BIT | prescaler | (irq ? PIOS_ARM_TIMER_IRQ_ENABLE : 0) | PIOS_ARM_TIMER_FREERUNNING_ENABLE | (enable ? PIOS_ARM_TIMER_ENABLE:0);<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> *   pios_arm_timer-&gt;control = val;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">**\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">pios_arm_timer_init<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">PIOS_ARM_TIMER_PRESCALE_256<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Nun erhalten wir Interrupts vom ARM-Timer.<\/p>\n<p>[1]&nbsp;<a href=\"https:\/\/github.com\/naums\/PiOS\">https:\/\/github.com\/naums\/PiOS<br\/>\n<\/a>[2]&nbsp;<a href=\"https:\/\/www.stefannaumann.de\/de\/2016\/05\/pilotos-prozesse\/\">https:\/\/www.stefannaumann.de\/de\/2016\/05\/pilotos-prozesse\/<\/a><br\/>\n[3]&nbsp;<a href=\"https:\/\/www.stefannaumann.de\/de\/2016\/05\/pilotos-prozesse-2-zustaende-und-blockierung\/\">https:\/\/www.stefannaumann.de\/de\/2016\/05\/pilotos-prozesse-2-zustaende-und-blockierung\/<\/a><br\/>\n[4]&nbsp;<a href=\"https:\/\/www.raspberrypi.org\/documentation\/hardware\/raspberrypi\/bcm2835\/BCM2835-ARM-Peripherals.pdf\">https:\/\/www.raspberrypi.org\/documentation\/hardware\/raspberrypi\/bcm2835\/BCM2835-ARM-Peripherals.pdf<\/a><br\/>\n[5]&nbsp;<a href=\"http:\/\/www.valvers.com\/open-software\/raspberry-pi\/step04-bare-metal-programming-in-c-pt4\/\">http:\/\/www.valvers.com\/open-software\/raspberry-pi\/step04-bare-metal-programming-in-c-pt4\/<\/a><br\/>\n[6]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/ch02s09s01.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/ch02s09s01.html<\/a><br\/>\n[7]&nbsp;<a href=\"http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/I2837.html\">http:\/\/infocenter.arm.com\/help\/index.jsp?topic=\/com.arm.doc.ddi0333h\/I2837.html<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"ARM"}},{"@attributes":{"term":"ARM Timer"}},{"@attributes":{"term":"Betriebssystem"}},{"@attributes":{"term":"Interrupt"}},{"@attributes":{"term":"IRQ"}},{"@attributes":{"term":"Operating System"}},{"@attributes":{"term":"PilotOS"}},{"@attributes":{"term":"PiOS"}},{"@attributes":{"term":"Prototype"}},{"@attributes":{"term":"Raspberry Pi"}},{"@attributes":{"term":"Timer"}}]},{"title":"Porting Micropython to Raspberry Pi","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/porting-micropython-to-raspberry-pi.html","rel":"alternate"}},"published":"2017-05-18T23:07:00+02:00","updated":"2017-05-18T23:07:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2017-05-18:\/informatik\/porting-micropython-to-raspberry-pi.html","summary":"<p><em>This article is in English for I hope it will be useful for someone who tries to port Micropython to new hardware as I do here.<\/em><\/p>\n<p>Micropython [1] is a very small Python interpreter, which can run on very restricted hardware. The pyboard is based on an STM32-F04 ARM processor \u2026<\/p>","content":"<p><em>This article is in English for I hope it will be useful for someone who tries to port Micropython to new hardware as I do here.<\/em><\/p>\n<p>Micropython [1] is a very small Python interpreter, which can run on very restricted hardware. The pyboard is based on an STM32-F04 ARM processor, with 1 KiB of Flash-ROM and 192 KiB of RAM. Micropython can and was ported to different hardware before. But the Raspberry Pi seems a bit overpowered im comparison to the F04-processor.<\/p>\n<p>This text describes the way to built a&nbsp;<strong>bare-metal&nbsp;<\/strong>port of Micropython for the Raspberry Pi. Using the article you will build a Micropython running on the Raspberry Pi as Operating System, there is no Unix running to aid Micropython with anything.<\/p>\n<h2 id=\"software-environment\"><strong>Software Environment<\/strong><\/h2>\n<p>I have to computer to build Micropython on: An Arch Linux&nbsp;and a (very old) Linux Mint 17.1. You will need the following software:<\/p>\n<ul>\n<li>arm-none-eabi-gcc<\/li>\n<li>arm-none-eabi-binutils<\/li>\n<\/ul>\n<p>Micropython does some calls to a C-library, which I use&nbsp;<strong>newlib&nbsp;<\/strong>[2] for. My code can be found under [3]. The Makefile contains rules for building newlib seperately by invoking&nbsp;<code>make newlib<\/code>. This will call &nbsp;the configure-script of newlib and compile it to a static libary especially for the Raspberry Pi.<\/p>\n<p>You will probably want to use a tool like Raspbootin [4] to transfer the binary to the Raspberry Pi. Raspbootin makes it possible to transmit compiled code to the Pi via a serial (i.e. UART) interface to the Pi.<\/p>\n<h3 id=\"details-on-the-newlib-build\">Details on the newlib-build<\/h3>\n<p>Building newlib for the Raspberry Pi was quite a challenge for me, as I struggled at first to build it with support for the Raspberry Pis Vector Floating Point Unit (VFPv2). The following setup seems to work fine:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code>CFLAGS_FOR_TARGET=\"-mcpu=arm1176jzf-s -mfpu=vfp -marm -mfloat-abi=hard\"<\/code><\/span>\n<span class=\"code-line\">configure --target=arm-none-eabi --enable-newlib-hw-fp --with-float=hard --with-cpu=arm1176jzf-s \\<\/span>\n<span class=\"code-line\">          --with-fpu=vfp --disable-multilib --disable-shared --enable-target-optspace  \\<\/span>\n<span class=\"code-line\">          --disable-newlib-supplied-syscalls<\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>At first I need to specify the CPU of the build, i.e. the CPU I want to build for. The Raspberry Pi BCM2835-chip contains a arm1176jzf-s processor. Be aware, that this only holds true for the Raspberry Pi 1 Model A, Model B+, etc. but not for the Raspberry Pi 2 or 3. Then I instruct the configure-script still inside the <em>CFLAGS_FOR_TARGET<\/em>-field, to build float-abi hard and vfp-support, and to emit ARM-code not code for the Thumb-mode of that processor.<\/p>\n<p>The configure call itself instructs configure to use the target arm-none-eabi, enables the hardware floating point unit, disables multilib, i.e. disables that a Thumb-version is build, disables that a shared libary is build and disables syscalls inside newlib. The latter is important because I do (did) not want to write Interrupt Service Routines for the Raspberry Pi (yet).<\/p>\n<h3 id=\"syscalls\">Syscalls<\/h3>\n<p>Newlib is a C-library. A C-library contains call which need syscalls for working correctly, for example <em>printf<\/em> needs a <em>write<\/em>-syscall so it can output anything to <em>stdout<\/em>. It is our job to implement <em>write<\/em>, so newlib can use the \"syscall\" and <em>printf<\/em> can output anything. David Welch also has code prepared for that job.<\/p>\n<h2 id=\"porting-micropython_1\">Porting Micropython<\/h2>\n<p>Porting Micropython to the Raspberry Pi was esentially quite easy - at least to get&nbsp;[any]{style=\"text-decoration: underline;\"} response from the Micropython. Esentially I took a lot of working code from David Welch, his AUX_UART-code to be exact and used that for the serial connection between the Raspberry Pi running Micropython and my PC. I was working on a clean rewrite of that code, but that did not work out that well yet, so I continue using this code for the time being.<\/p>\n<p>I starting with the folder&nbsp;<em>bare-arm<\/em> and started tweaking its Makefile until it built binaries for the Raspberry Pi. The bare-arm-port is written for an Cortex-M4 processor, which in turn I needed to replace with the ARM1176jzf-s processor of the Raspberry Pi.<\/p>\n<h3 id=\"port-structure\">Port&nbsp;structure<\/h3>\n<p>The folder contains the following files, which are or may be important to your port:<\/p>\n<ul>\n<li><em>Makefile<\/em> - duh!<\/li>\n<li><em>mphalport.h<\/em> - I did not really use that file, so I don't know what it was for<\/li>\n<li><em>mphalconfigport.h<\/em> - defines loads of options how to build Micropython. You can change a lot of builtin-stuff here<\/li>\n<li><em>qstrdefsport.h<\/em> - defines QStrings, which are used by your port specifically<\/li>\n<li><em>kernel.ld<\/em> - The Linker skript<\/li>\n<\/ul>\n<h4 id=\"on-qstrings\">On QStrings<\/h4>\n<p>The QStrings are strings, which are held only once in Memory even if they are used by two completely separate parts of the code. The&nbsp;reason why you have to write them there in the following way, is that the build-process creates constants from them and builds them into Micropython only once. It needs to check whether any string is used twice and build it only once.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"n\">Q<\/span><span class=\"p\">(<\/span><span class=\"n\">hello<\/span><span class=\"p\">)<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"n\">Q<\/span><span class=\"p\">(<\/span><span class=\"n\">inc<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">Q<\/span><span class=\"p\">(<\/span><span class=\"n\">dec<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"n\">Q<\/span><span class=\"p\">(<\/span><span class=\"n\">offset<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ ...<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>More on these QStrings in a future article.<\/p>\n<h4 id=\"configuring-the-builtins-of-the-port\">Configuring the builtins of the port<\/h4>\n<p>Using preprocessor-statements in the file&nbsp;<em>mphalconfigport.h&nbsp;<\/em>you can change what parts of Micropython are built into the binary. This may be essential to ports to hardware with very limited resources, as every module, which is built into CPython by default can increase the binary size and in turn the memory footprint of the interpreter at run-time.<\/p>\n<p>The options are endless. For a (I believe not complete) list of options and a very short description on what they do you can consult the file&nbsp;<em>\/py\/mpconfig.h<\/em> in the project repository [5].<\/p>\n<p>There are very important other options there. For example you have to define what modules are built into Micropython, maybe you want to write module for it yourself to use in your Python code. But more on this in a later article. Also there is the macro&nbsp;<em>[MP_PLAT_PRINT_STRN]{.pl-en}([str, len]{.pl-v})&nbsp;<\/em>which you have to define as a print-function. I used it as macro for&nbsp;a print-string-function, which prints a string through the UART-interface of the Raspberry Pi.<\/p>\n<h4 id=\"the-linker-script\">The linker script<\/h4>\n<p>The linker script tells our linker where a particular part of our code should be placed in the binary. I used the <em>kernel.ld<\/em> linker script of the Baking Pi-Tutorial [6]. This is a quite simple script but defines all the needed areas which are used by our compiler and states where they should be placed.<\/p>\n<h3 id=\"the-more-complete-picture_1\">The more complete picture<\/h3>\n<p>After adding some important information, like that I want to link the binary against newlibs <em>libc<\/em> and <em>libm<\/em>-libraries and the <em>libgcc<\/em> I need to add the code-files that should be built into Micropython. This can be done by adding them to the <em>SRC_C<\/em> and the <em>SRC_S<\/em>-Variables (for Assembler-files).<\/p>\n<p>At first I had only one Assembler-file (<em>startup_rpi.s<\/em>) which directly jumped into the main-routine which is defined in a C-file:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"na\">.section<\/span><span class=\"w\"> <\/span><span class=\"no\">.init<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"na\">.globl<\/span><span class=\"w\"> <\/span><span class=\"no\">_start<\/span><\/span>\n<span class=\"code-line\"><span class=\"na\">.globl<\/span><span class=\"w\"> <\/span><span class=\"no\">blinkloop<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nl\">_start:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nf\">mov<\/span><span class=\"w\"> <\/span><span class=\"no\">sp<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">#0<\/span><span class=\"no\">x8000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nf\">bl<\/span><span class=\"w\"> <\/span><span class=\"no\">main<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nl\">blinkloop:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ ...<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nf\">b<\/span><span class=\"w\"> <\/span><span class=\"no\">blinkloop<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>The main-routine then sets up the Micrpython and runs little test-skripts.&nbsp;It also needs to set the stack accordingly, so that Micropython will not run out of memory instandly. On the first run I expect the code to just run and work perfectly, but instead the statements fail, which I find very interesting. The follwing code was basically copied from the <em>bare-arm<\/em>-folder.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">do_str<\/span><span class=\"p\">(<\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">src<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_parse_input_kind_t<\/span><span class=\"w\"> <\/span><span class=\"n\">input_kind<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mp_lexer_t<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">lex<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_lexer_new_from_str_len<\/span><span class=\"p\">(<\/span><span class=\"n\">MP_QSTR__lt_stdin_gt_<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">src<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">strlen<\/span><span class=\"p\">(<\/span><span class=\"n\">src<\/span><span class=\"p\">),<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">lex<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">nlr_buf_t<\/span><span class=\"w\"> <\/span><span class=\"n\">nlr<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">nlr_push<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">nlr<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">qstr<\/span><span class=\"w\"> <\/span><span class=\"n\">source_name<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">lex<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">source_name<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_parse_tree_t<\/span><span class=\"w\"> <\/span><span class=\"n\">parse_tree<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_parse<\/span><span class=\"p\">(<\/span><span class=\"n\">lex<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">input_kind<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_obj_t<\/span><span class=\"w\"> <\/span><span class=\"n\">module_fun<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">mp_compile<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">parse_tree<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">source_name<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_EMIT_OPT_NONE<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_call_function_0<\/span><span class=\"p\">(<\/span><span class=\"n\">module_fun<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">nlr_pop<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ uncaught exception<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mp_obj_print_exception<\/span><span class=\"p\">(<\/span><span class=\"o\">&amp;<\/span><span class=\"n\">mp_plat_print<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">mp_obj_t<\/span><span class=\"p\">)<\/span><span class=\"n\">nlr<\/span><span class=\"p\">.<\/span><span class=\"n\">ret_val<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">argc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">**<\/span><span class=\"n\">argv<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mp_init<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">do_str<\/span><span class=\"p\">(<\/span><span class=\"s\">\"print('hellp world')\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_PARSE_SINGLE_INPUT<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">do_str<\/span><span class=\"p\">(<\/span><span class=\"s\">\"print('hello world!', list(x+1 for x in range(10)), end='eol<\/span><span class=\"se\">\\\\<\/span><span class=\"s\">n')\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_PARSE_SINGLE_INPUT<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">do_str<\/span><span class=\"p\">(<\/span><span class=\"s\">\"for i in range(10):<\/span><span class=\"se\">\\n<\/span><span class=\"s\">  print(i)\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">MP_PARSE_FILE_INPUT<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mp_deinit<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>*&nbsp;do_str<em> takes two parameters. The second parameter is in accordance&nbsp;to the Python-function <\/em>compile*. Using single-input force Micropython to interpret the statement as single statement and therefore will only interpret a single statement at a time, whereas file-input allows for bigger scripts.<\/p>\n<h2 id=\"the-bigger-picture_1\">The bigger picture<\/h2>\n<p>Now we have a running Micropython interpreter on Raspberry Pi running without an Operating System. Of course this Micropython can not be used for anything at the moment, there are basically no drivers, there is no video output, no GPIO-controlling and no input or output. So there is still a lot of work to do for the Raspberry Pi port to become finished or usable. But this is a start, even if a very small one.<\/p>\n<p>But I do not only aim at porting Micropython but also at documenting it along the way as far as I'm comfortable. The code of Micropython is largely without any useful comments, functions are used, and a new developer has no chance but to guess what a function name may mean or what this function could possibly do.<\/p>\n<h3 id=\"todo\">ToDo<\/h3>\n<ul>\n<li>Build some sort of REPL or interactive mode, so automatic testing becomes trivial<\/li>\n<li>Run longer Python code and find out why it fails and\/or crashes<\/li>\n<\/ul>\n<p>[1]&nbsp;<a href=\"https:\/\/www.micropython.org\">micropython.org<\/a><br\/>\n[2]&nbsp;<a href=\"https:\/\/sourceware.org\/newlib\/\">sourceware.org\/newlib<\/a><br\/>\n[3]&nbsp;<a href=\"https:\/\/www.github.com\/naums\/micropython\">github.com\/naums\/micropython<\/a><br\/>\n[4]&nbsp;<a href=\"https:\/\/github.com\/naums\/raspbootin\">github.com\/naums\/raspbootin<br\/>\n<\/a>[5]&nbsp;<a href=\"https:\/\/github.com\/micropython\/micropython\/blob\/master\/py\/mpconfig.h\">github.com\/micropython\/micropython\/blob\/master\/py\/mpconfig.h<br\/>\n<\/a>[6]&nbsp;<a href=\"http:\/\/www.cl.cam.ac.uk\/projects\/raspberrypi\/tutorials\/os\/\">cl.cam.ac.uk\/projects\/raspberrypi\/tutorials\/os\/<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Bare Metal"}},{"@attributes":{"term":"Betriebssystem"}},{"@attributes":{"term":"CPython"}},{"@attributes":{"term":"Micropython"}},{"@attributes":{"term":"Operating System"}},{"@attributes":{"term":"Port"}},{"@attributes":{"term":"Python"}},{"@attributes":{"term":"Raspberry Pi"}}]},{"title":"Massenhinzuf\u00fcgen von Nutzern zu Kimai (1.1.0)","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/massenhinzufuegen-von-nutzern-zu-kimai-1-1-0.html","rel":"alternate"}},"published":"2016-10-12T22:46:00+02:00","updated":"2016-10-12T22:46:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-10-12:\/informatik\/massenhinzufuegen-von-nutzern-zu-kimai-1-1-0.html","summary":"<p>Kimai [1] ist ein web-basiertes Tool um Arbeitszeiten zu erfassen, sei es um Arbeitszeiten von Mitarbeitern eines Betriebs bzw. Projekts zu erfassen oder um die eigentliche Arbeitsbelastung von Studierenden in Lehrveranstaltungen zu erfassen. Kimai kann Projekte, T&auml;tigkeiten, Kunden verwalten, Rechnungen (wenn ein Stundenlohn eingetragen wurde) drucken, die Daten exportieren, etc \u2026<\/p>","content":"<p>Kimai [1] ist ein web-basiertes Tool um Arbeitszeiten zu erfassen, sei es um Arbeitszeiten von Mitarbeitern eines Betriebs bzw. Projekts zu erfassen oder um die eigentliche Arbeitsbelastung von Studierenden in Lehrveranstaltungen zu erfassen. Kimai kann Projekte, T&auml;tigkeiten, Kunden verwalten, Rechnungen (wenn ein Stundenlohn eingetragen wurde) drucken, die Daten exportieren, etc.&nbsp;Kimai ist ein sehr m&auml;chtiges Tool. Neben dem hinzuf&uuml;gen mit bekannten Start- und Enddatum \/ Zeit kann auch ein tracken angeschaltet werden, d.h. Kimai nimmt die Zeit zwischen zwei Knopfdr&uuml;cken auf.<\/p>\n<p>Hier geht es aber darum das Tool zur Lehrevaluation an einer Universit&auml;t zu verwenden. Genauer soll es darum gehen die Studierenden zu befragen, wie viel Zeit sie f&uuml;r eine bestimmte Lehrveranstaltung genau ben&ouml;tigen. Dabei ist es wichtig, dass die Studierenden eine intuitive Oberfl&auml;che haben und immer im Semester an&nbsp;ihre Daten kommen. Leider ist Kimai nicht an allen Stellen intuitiv, ich hoffe aber, dass die Informatik-Studierenden trotzdem mit dem Tool klar kommen.<\/p>\n<p>Leider kann Kimai auch nicht mehrere Nutzer auf einmal hinzuf&uuml;gen, was aber f&uuml;r den Anwendungszweck zwingend erforderlich ist, weil die Studierenden nat&uuml;rlich pseudonymisiert erfasst werden sollen. Nach einiges an Zeit habe ich folgende Entdeckungen gemacht:<\/p>\n<ul>\n<li><em>includes\/autoconf.php<\/em> enth&auml;lt neben Passworten f&uuml;r die Datenbank auch das Passwort-Salt f&uuml;r die Nutzer von Kimai<\/li>\n<li><em>includes\/func.php<\/em> enth&auml;lt die Funktion, die die Passwort-Hashes erzeugt (<em>md5(\\$salt.\\$password.\\$salt)<\/em>);<\/li>\n<\/ul>\n<p>Das k&ouml;nnen wir uns zu Nutze machen, indem wir die Passwort-Hashes selbst erzeugen, Nutzernamen festlegen und in die Datenbank eintragen. Dabei gibt es zwei spannende Datenbanktabellen (ich verwende die Tabellen mit dem Prefix 'kimai').<\/p>\n<ul>\n<li><em>kimai_users<\/em> enth&auml;lt die Nutzer, deren Passwort, Zustand, globale Rolle<\/li>\n<li><em>kimai_groups_users<\/em> enth&auml;lt die Zuordnung der Users zu den Gruppen und Rollen innerhalb der Gruppe<\/li>\n<\/ul>\n<p>Zur Erkl&auml;rung: in Kimai kann ein Nutzer eine globale Rolle haben, bspw. Nutzer, aber im Kontext eines Projekts (Gruppe) eine h&ouml;her gestellte Rolle einnehmen bspw. Groupleader. Was die Rolle alles darf, ist dann im Tool festzulegen und wird auch in der Datenbank (allerdings einer anderen Tabelle) gespeichert.<\/p>\n<p>Die Nutzer erhalten einen Namen, eine ID (hochz&auml;hlen reicht da, obwohl Kimai beim Erstellen eine zuf&auml;llige ID festlegt) und ein Passwort Hash. Weiter werden in <em>kimai_users<\/em> Eintr&auml;ge ben&ouml;tigt f&uuml;r die globale Gruppierung. F&uuml;r Nutzer des Systems gen&uuml;gt es, wenn Sie die \"Users\"-Rolle haben, d.h. keine Nutzer hinzuf&uuml;gen oder ver&auml;ndern k&ouml;nnen. Auch sollte datenschutzrechtlich gekl&auml;rt sein, dass kein Nutzer die Eintragungen eines anderen Nutzers sehen darf. Der Wert 2 stellt (jedenfalls in der Standardsituation) die globale Rolle \"User\" dar.<\/p>\n<p>Die Gruppenzuordnung bedarf einer etwas genaueren Betrachtung. Zun&auml;chst legen wir im Tool eine Gruppe an, dann einen Kunden, ein Projekt und T&auml;tigkeiten in dem Projekt. Das Projekt k&ouml;nnen wir dann der neuen Gruppe zuordnen, sodass alle Mitglieder der Gruppe in dieses Projekt Arbeit stecken k&ouml;nnen. In der Tabelle <em>kimai_groups_users<\/em>&nbsp; wird dann die Nutzer-ID, der Gruppenname und die Rolle innerhalb der Gruppe (siehe dazu die gruppenspezifischen Rollen) eingetragen.<\/p>\n<p>Folgendes Skript erzeugt 50 Nutzer, jeweils mit einem Passwort (hier entfernt), erzeugt die SQL-Statements und eine tex-Datei, die alle Nutzerdaten enth&auml;lt. Zu letzterem wird eine Art Wrapper ben&ouml;tigt, die einen sinnvollen Kontext bietet, bspw. eine Art Fragebogen oder Code, der die Zugangsdaten sinnvoll formatiert, damit ein Ausschneiden kleinerer Zettel f&uuml;r jeden Teilnehmer m&ouml;glich wird.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">&lt;?php<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nv\">$rootname<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"kimai_nutzer_\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">$insert<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">$group<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nv\">$tex<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">$fmt<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">$fmt<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"<\/span><span class=\"se\">\\t<\/span><span class=\"s2\">extbf{Zugangsdaten}<\/span><span class=\"se\">\\\\<\/span><span class=\"s2\">Nutzername: %s<\/span><span class=\"se\">\\\\<\/span><span class=\"s2\">Passwort: <\/span><span class=\"si\">$s<\/span><span class=\"se\">\\\\<\/span><span class=\"s2\">URL: kimai.org\"<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nv\">$salt<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"ein Salt\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"k\">for<\/span> <span class=\"p\">(<\/span><span class=\"nv\">$i<\/span><span class=\"o\">=<\/span><span class=\"mi\">1<\/span><span class=\"p\">;<\/span> <span class=\"nv\">$i<\/span><span class=\"o\">&lt;=<\/span><span class=\"mi\">50<\/span><span class=\"p\">;<\/span> <span class=\"nv\">$i<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\">    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nv\">$i<\/span><span class=\"o\">&lt;<\/span><span class=\"mi\">10<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\">        <span class=\"nv\">$usrname<\/span> <span class=\"o\">=<\/span> <span class=\"nv\">$rootname<\/span><span class=\"o\">.<\/span><span class=\"s2\">\"0\"<\/span><span class=\"o\">.<\/span><span class=\"nv\">$i<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\">    <span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\">        <span class=\"nv\">$usrname<\/span> <span class=\"o\">=<\/span> <span class=\"nv\">$rootname<\/span><span class=\"o\">.<\/span><span class=\"nv\">$i<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">    <span class=\"nv\">$passwd<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\">    <span class=\"sd\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"sd\">     * Passowrt Generierung hier!<\/span><\/span>\n<span class=\"code-line\"><span class=\"sd\">     **\/<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">    <span class=\"nv\">$hash<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">md5<\/span> <span class=\"p\">(<\/span> <span class=\"nv\">$salt<\/span><span class=\"o\">.<\/span><span class=\"nv\">$passwd<\/span><span class=\"o\">.<\/span><span class=\"nv\">$salt<\/span> <span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nv\">$i<\/span><span class=\"o\">&gt;<\/span><span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\">        <span class=\"nv\">$insert<\/span><span class=\"o\">.=<\/span><span class=\"s2\">\",\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\">        <span class=\"nv\">$group<\/span> <span class=\"o\">.=<\/span><span class=\"s2\">\",\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\">    <span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\">    <span class=\"nv\">$insert<\/span> <span class=\"o\">.=<\/span> <span class=\"s2\">\"(<\/span><span class=\"si\">$i<\/span><span class=\"s2\">, '<\/span><span class=\"si\">$usrname<\/span><span class=\"s2\">', NULL, 0, 1, '',  '<\/span><span class=\"si\">$hash<\/span><span class=\"s2\">', NULL, 0,0, '0', 1, 1, 0, 0, 0, NULL, 2)\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\">    <span class=\"nv\">$group<\/span> <span class=\"o\">.=<\/span> <span class=\"s2\">\"(2, <\/span><span class=\"si\">$i<\/span><span class=\"s2\">, 2)\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\">    <span class=\"nv\">$tex<\/span><span class=\"o\">.=<\/span><span class=\"nb\">sprintf<\/span><span class=\"p\">(<\/span><span class=\"nv\">$fmt<\/span><span class=\"p\">,<\/span> <span class=\"nb\">str_replace<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"_\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"\\_\"<\/span><span class=\"p\">,<\/span> <span class=\"nv\">$usrname<\/span><span class=\"p\">),<\/span> <span class=\"nv\">$passwd<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nv\">$q<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">fopen<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"query.sql\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"w+\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">$g<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">fopen<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"group.sql\"<\/span><span class=\"p\">,<\/span> <span class=\"s2\">\"w+\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">$query<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"INSERT INTO kimai_users (userId, name, alias, trash, active, mail, <\/span><\/span>\n<span class=\"code-line\"><span class=\"s2\">                    password, passwordResetHash, ban, banTIme, secure, <\/span><\/span>\n<span class=\"code-line\"><span class=\"s2\">                    lastProject, lastActivity, lastRecord, timeframeBegin, <\/span><\/span>\n<span class=\"code-line\"><span class=\"s2\">                    timeframeEnd, apikey, globalRoleId) VALUES \"<\/span><span class=\"o\">.<\/span><span class=\"nv\">$insert<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">$groupquery<\/span><span class=\"o\">=<\/span><span class=\"s2\">\"INSERT INTO kimai_groups_users (groupID, userID, membershipRoleID) VALUES <\/span><span class=\"si\">$group<\/span><span class=\"s2\">\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nb\">fwrite<\/span> <span class=\"p\">(<\/span><span class=\"nv\">$q<\/span><span class=\"p\">,<\/span> <span class=\"nv\">$query<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">fclose<\/span><span class=\"p\">(<\/span><span class=\"nv\">$q<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">fwrite<\/span> <span class=\"p\">(<\/span><span class=\"nv\">$g<\/span><span class=\"p\">,<\/span> <span class=\"nv\">$groupquery<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"nb\">fclose<\/span><span class=\"p\">(<\/span><span class=\"nv\">$g<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">echo<\/span> <span class=\"nv\">$tex<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">?&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Die Dateien <em>query.sql<\/em> und <em>group.sql<\/em> werden dann entweder &uuml;ber Tools wie phpMyAdmin [2] importiert oder &uuml;ber das&nbsp;<em>mysql<\/em>-Kommdozeilenwerkzeug nach dem Ausw&auml;hlen der richtigen Datenbank (<em>USE \\&lt;datenbankname&gt;<\/em>) &uuml;ber das Kommando <em>source<\/em> geladen.<\/p>\n<p>Hinweise: Wenn Nutzer \"automatisch\" hinzugef&uuml;gt werden solltet ihr darauf achten, dass keinesfalls Nutzer mit der gleichen ID bereits existieren. Weiter sollten am Besten keine Zeiten gespeichert sein, vor allem nicht unter einer userID, die ihr verwenden wollt f&uuml;r einen neuen Nutzer. Auch sollten gel&ouml;schte Nutzer im Idealfall nicht existieren.<\/p>\n<p>[1] <a href=\"http:\/\/kimai.org\">kimai.org<\/a><br\/>\n[2] <a href=\"http:\/\/phpmyadmin.net\">phpmyadmin.net<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Arbeitszeit"}},{"@attributes":{"term":"Evaluation"}},{"@attributes":{"term":"Fachschaft"}},{"@attributes":{"term":"Hochschule"}},{"@attributes":{"term":"Kimai"}},{"@attributes":{"term":"Lehre"}},{"@attributes":{"term":"Studium"}},{"@attributes":{"term":"Universit\u00e4t"}},{"@attributes":{"term":"Vorlesung"}}]},{"title":"Gstreamer: eine Einf\u00fchrung","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/gstreamer-eine-einfuehrung.html","rel":"alternate"}},"published":"2016-06-12T11:19:00+02:00","updated":"2016-06-12T11:19:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-06-12:\/informatik\/gstreamer-eine-einfuehrung.html","summary":"<p>Aktuell besch&auml;ftige ich mich mit Gstreamer. Mein Ziel ist es dabei mithilfe von Gstreamer und Snowmix [2] eine Pipeline aufzubauen, mithilfe derer ich mit meiner vorhandenen Hardware auf Yotube oder Twitch streamen kann. Das aktuelle ffmpeg kommt mit meiner Hardware bzw. video4linux2 nicht mehr so ganz klar, weshalb Tools wie \u2026<\/p>","content":"<p>Aktuell besch&auml;ftige ich mich mit Gstreamer. Mein Ziel ist es dabei mithilfe von Gstreamer und Snowmix [2] eine Pipeline aufzubauen, mithilfe derer ich mit meiner vorhandenen Hardware auf Yotube oder Twitch streamen kann. Das aktuelle ffmpeg kommt mit meiner Hardware bzw. video4linux2 nicht mehr so ganz klar, weshalb Tools wie OBS-Studio ausfallen.<\/p>\n<p>Diese Einf&uuml;hrung soll lediglich Gstreamer motivieren und die Grundfunktionsweise erkl&auml;ren. Details lasse ich dabei erst mal au&szlig;en vor, um einen einfachen Einstieg in Gstreamer zu erm&ouml;glichen. Auch Streaming-Verfahren, Codecs, etc werden hier nicht behandelt, ich setze ein grundlegenden Wissen dar&uuml;ber voraus. Ich verwende Arch Linux und gstreamer 1.0. Die erforderlichen Pakete sind stark von der Linux-Distribution abh&auml;ngig, meist <em>gstreamer<\/em> und <em>gstreamer-plugins-*<\/em>. Helfen wird sicherlich auch <em>gstreamer-libav.<\/em> Unter Arch Linux hei&szlig;en die Gstreamer 1.0-Pakete <em>gst-*.<\/em><\/p>\n<h4 id=\"gstreamer-als-pipeline\">Gstreamer als Pipeline<\/h4>\n<p>Machen wir uns zuerst die Funktionsweise von Gstreamer bewusst. Gstreamer ist als eine Pipeline aufgebaut worden, die Elemente (elements) der Pipeline wird dabei meist durch Plugins realisiert. Die meisten Plugins haben Quelle(n) und Senke(n) (source, sink). Durch die Verbindung zwischen den Elementen k&ouml;nnen Videodaten von einem Element der Kette zum n&auml;chsten gebracht werden. Gstreamer setzt dabei oftmals auf shared memory, d.h. auf Speicher, der von allen Elementen adressiert werden kann, wodurch ein &Uuml;bergeben von Daten auf die Dereferenzierung eines Zeigers hinausl&auml;uft.<\/p>\n<p>Die Elemente der Pipeline erhalten Daten vom vorherigen Element, verarbeiten die Daten und geben die Daten weiter an das nachfolgende Element der Pipeline. Quellen erzeugen Videodaten, Senken zerst&ouml;ren Daten (wobei meist zuvor noch eine Aktion wie Anzeigen mit den Daten gemacht wird). Jede Pipelinestufe ben&ouml;tigt Zeit, wodurch eine Latenz entsteht zwischen dem Eingeben der Daten und dem Ausgeben der Daten. Gstreamer kann nicht nur mit Videodaten arbeiten sondern auch mit Audiodaten; will man beides gemeinsam aus einer Datei auslesen, muss das Signal vor der Anzeige \/ dem Abspielen demultiplext werden, also die Audiodaten m&uuml;ssten von den Videodaten getrennt werden (demux), dann kann die Verarbeitung in zwei (oder mehr) Str&auml;ngen der Pipeline parallel weiterlaufen.<\/p>\n<p>Folgende Darstellung der Pipeline ist aus [1] entnommen:<\/p>\n<p><img alt=\"Gstreamer-Pipeline\" height=\"82\" src=\"http:\/\/www.z25.org\/static\/_rd_\/videostreaming_intro_plab\/basic-pipelines.png\" width=\"902\"\/><\/p>\n<h4 id=\"eine-erste-pipeline\">Eine erste Pipeline<\/h4>\n<p>Als erstes Experiment verwenden wir die <em>testvideosrc,<\/em> die ein Testbild erzeugt und die <em>autovideosink<\/em>, die die eingegebenen Videodaten anzeigt. Um die Pipeline zu erstellen verwende ich hier <em>gst-launch-1.0,<\/em> was f&uuml;r die Gstreamer Entwickler eine Art Test-tool darstellt. Mithilfe der Programmiersprache C (oder anderen Sprachen), kann mit dem Gstreamer SDK programmiert werden um anspruchsvollere Anwendungen zu erzeugen. Damit besch&auml;ftige ich mich hier erst mal nicht, daf&uuml;r empfehle ich die Gstramer Dokumentation [3].<\/p>\n<p>Die erste Pipeline verwendet die <em>testvideosrc<\/em> um Videodaten zu erzeugen, die in die <em>autovideosink<\/em> eingespeist werden:<\/p>\n<blockquote>\n<p>gst-launch-1.0 videotestsrc ! autovideosink<\/p>\n<\/blockquote>\n<p>Die Pipeline-Stufen werden mit ! verbunden. Es sollte ein Fenster erscheinen, was das Testbild anzeigt:<\/p>\n<p><a href=\"\/data\/thumbnail\/gstreamer_full.jpg\"><img alt=\"gstreamer1_testvideo\" class=\"alignnone size-full wp-image-372\" height=\"265\" src=\"\/data\/thumbnail\/gstreamer_full.jpg\" width=\"322\"\/><\/a><\/p>\n<h4 id=\"ein-erster-stream\">Ein erster Stream<\/h4>\n<p>Hier soll nun noch gezeigt werden, wie die Videodaten mittels dem Motion-JPEG-Verfahren komprimiert und mit RTP &uuml;ber das Netzwerk verschickt werden und dort mittels gstreamer angezeigt werden. Dazu erweitern wir schrittweise unsere Pipeline. Zun&auml;chst k&ouml;nnen wir die Pipeline durch eine Operation und die Gegenoperation erweitern, bspw. werden wir die Bilder der <em>videotestsrc<\/em> mit <em>jpegenc<\/em> enkodieren, und mit <em>jpegdec<\/em> dekodieren. Am Ergebnis sollte sich nur marginale qualitative Unterschiede zeigen.<\/p>\n<blockquote>\n<p>gst-launch-1.0 videotestsrc ! jpegenc ! jpegdec ! autovideosink<\/p>\n<\/blockquote>\n<p>&Uuml;ber weitere Parameter an <em>jpegenc<\/em> kann der Enkodierschritt weiter parametrisiert werden. Bspw. k&ouml;nnen wir eine JPEG-Qualit&auml;t angeben:<\/p>\n<blockquote>\n<p>gst-launch-1.0 videotestsrc ! jpegenc quality=20 ! jpegdec ! autovideosink<\/p>\n<\/blockquote>\n<p>Die Qualit&auml;t des angezeigten Bildes sollte stark schlechter sein, als die oben gezeigte. Wir erweitern die Pipeline weiter durch <em>rtpjpegpay<\/em> und <em>rtpjpegdepay<\/em> um die JPEG-Daten in RTP-Pakete einzuteilen.<\/p>\n<blockquote>\n<p>gst-launch-1.0 videotestsrc ! jpegenc ! rtpjpegpay ! rtpjpegdepay ! jpegdec ! autovideosink<\/p>\n<\/blockquote>\n<p>Und zu guter Letzt verschicken wir die Daten per UDP an uns selbst (127.0.0.1) an den Port 5200, in der Hoffnung am Zielrechner gibt es einen Prozess der diesen Port belauscht und Videodaten anzeigen will. Jetzt m&uuml;ssen wir die Pipeline allerdings aufteilen in einen Server-Teil und einen Client-Teil, weil <em>udpsink<\/em> kein Quellpad und <em>udpsrc<\/em> kein Senkenpad mehr besitzt. Pad ist die Bezeichnung der Quellen bzw. Senken in einem Plugin. Zwischen den Pads k&ouml;nnen in Plugins noch so genannte Caps (Capabilities) festgelegt werden, die dem nachfolgenden Element mitteilen, welche Art von Stream er erwarten soll. Setzen wir das gesamte Wissen zusammen erhalten wir f&uuml;r den Server:<\/p>\n<blockquote>\n<p>gst-launch-1.0 videotestsrc ! jpegenc quality=80 ! rtpjpegpay ! udpsink host=127.0.0.1 port=5200<\/p>\n<\/blockquote>\n<p>Und f&uuml;r den Client m&uuml;ssen wir die Caps angeben, weil rtpjpegdepay sonst nicht wei&szlig; um welche Daten es sich handelt, die aus <em>udpsrc<\/em> herausfallen. Gstreamer ist so generisch gehalten, dass damit prinzipiell jede Art von Stream verarbeitet werden kann, d.h. <em>udrsrc<\/em> wei&szlig; erstmal nicht, welche Daten es da eigentlich bekommt.<\/p>\n<blockquote>\n<p>gst-launch-1.0 udpsrc port=5200 caps=application\/x-rtp ! rtpjpegdepay ! jpegdec ! autovideosink<\/p>\n<\/blockquote>\n<p>Um bspw. Dateien zu &ouml;ffnen, kann <em>filesrc<\/em> anstelle von <em>videotestsrc<\/em> verwendet werden, um Video4Linux2 Ger&auml;te zu verwenden benutzt man <em>v4l2src<\/em> mit dem Parameter <em>device<\/em>.<\/p>\n<h4 id=\"literatur\">Literatur<\/h4>\n<p>[1] <a href=\"http:\/\/www.z25.org\/static\/_rd_\/videostreaming_intro_plab\/\">http:\/\/www.z25.org\/static\/_rd_\/videostreaming_intro_plab\/<\/a><br\/>\n[2] <a href=\"http:\/\/snowmix.sourceforge.net\/\">http:\/\/snowmix.sourceforge.net\/<\/a><br\/>\n[3] <a href=\"https:\/\/gstreamer.freedesktop.org\/data\/doc\/gstreamer\/head\/manual\/html\/index.html\">https:\/\/gstreamer.freedesktop.org\/data\/doc\/gstreamer\/head\/manual\/html\/index.html<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Audio"}},{"@attributes":{"term":"Gstreamer"}},{"@attributes":{"term":"JPEG"}},{"@attributes":{"term":"linux"}},{"@attributes":{"term":"Snowmix"}},{"@attributes":{"term":"Streaming"}},{"@attributes":{"term":"Video"}}]},{"title":"PilotOS: Processes 2 (Process states and mutual exclusion)","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/pilotos-processes-2.html","rel":"alternate"}},"published":"2016-05-22T10:00:00+02:00","updated":"2016-05-22T10:00:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-05-22:\/informatik\/pilotos-processes-2.html","summary":"<p>The last article about processes had a concrete implementation in mind, with this article there is no implementation in PilotOS (yet). Therefore I will write some theory about processes, their states and mutual exclusion.<\/p>\n<p>A process is a unit of execution or code, which can be executed. With this definition \u2026<\/p>","content":"<p>The last article about processes had a concrete implementation in mind, with this article there is no implementation in PilotOS (yet). Therefore I will write some theory about processes, their states and mutual exclusion.<\/p>\n<p>A process is a unit of execution or code, which can be executed. With this definition we don't care whether the code really can be executed now, it is enough, that the code is \"ready\" to be executed, so the code can be jumped to, has got some memory and could be executed in theory. In real operating systems there are several constraints about the point in time when a process can be executed. Therefore there are process states.<\/p>\n<p>The state of a process determines in what state of an automaton the process is right now. A process can be executed only if it is in the main memory (see virtual memory, MMU, paging) und does not wait for other processes to finish. A process may be waiting for other processes if they want to use the same resource, which can only be used exclusively and the other process has allocated them.<\/p>\n<p>Resources will be managed by the operating system. There as physical and logical resources, eg. for physical ones hard-drive or memory; a file may be logical. To ensure secure access to these resources there are means for mutual exclusion (mutex) in most operating systems. These are used to ensure, that there can only be one (or in general k) processes executing a critical section at one point in time. A critical section is code, which, when executed by several processes concurrently, may lead to harm, which can not be undone.<\/p>\n<p>There are several design critia for the implementation of mutexes. For example livelyness, i.e. a process does not keep a resource an infinite amount of time. Security, i.e. something bad, that can not be undone, may never happen. And fairness, which can be definited differently, but we will use the following definition: no process will wait indefinitely. With these criteria one can implement a policy, which determines when and how waiting processes will be unblocked.<\/p>\n<p>The blocking of a process can be done by the process itself (by sending the request to be blocked until a condition is fulfilled to the operating system), or by the operating system, while accessing a resource. For example it is sometimes necessary to wait for another process to finish a certain action, so they can work in synchron.<\/p>\n<p>A first implementation of waiting could be a busy wait, i.e. a while-loop in the code, which tests the condition. Only if it is fulfilled, the following code can be executed (safely). But this method is really heavy on computing-time, because the scheduler has to schedule this process, and it will use its complete time-interval only for testing a variable.<\/p>\n<p>It would be more reasonable to not schedule this task again, until the condition is met. For this we set the process state to \"waiting\" or \"blocked\", which indicates, that the process is waiting for some condition to be fulfilled. The condition must the saved also (for example as mutex-descriptor). In the moment this mutex will be cleared, the operating system may unblock every (or any one) of the processes waiting for that condition, be setting their state to \"active\".<\/p>\n<p>That means we have the following three process states: \"running\", i.e. the process is executed by the CPU at this point in time; \"active\" - the process is waiting for the CPU but can be executed and \"blocked, waiting\" - the process is waiting for a mutex to be cleared.<\/p>\n<p>A mutex can be cleared differently. In normal operating systems, there are semaphores, and also monitors. And it can be implemented with the help of a boolean-Variable. But with several processes it become non-trivial to implement a mutex. On entrance into the critical section the process must check if the variable is set (or the semaphore has reached a certain number). If so, then the process must wait.<\/p>\n<p>If the variable is not set, the process may enter the critical section and has to set the variable with a second instruction. If it is preempted between these two instruction, then a second process may be allowed to enter the critical section and something bad may happen (see race conditions). Therefore most of the processes have an instruction, that sets a variable and returns if it was set, so no other process may enter the critical section.<\/p>\n<p>Alternatively for the time, the process is in the critical section, it may disable the interrupts in the CPU. This in turn means, thet the process can not be interrupted by timer-interrupts, and therefore can not be interrupted by any process in general. If this method is used the programmer must be very aware, that his\/her critical section must be as short as possible, because it would bring the system down to a crawl, because no ther process can be executed in the mean-time. In turn, the interrupts may only be disabled for the time-interval the variable is tested and set, and afterwards can be activated again.<\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"inter-process-communication"}},{"@attributes":{"term":"Mutex"}},{"@attributes":{"term":"Operating System"}},{"@attributes":{"term":"PilotOS"}},{"@attributes":{"term":"process"}},{"@attributes":{"term":"process-stated"}}]},{"title":"PilotOS: Prozesse 2 (Zust\u00e4nde und Blockierung)","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/pilotos-processes-2-de.html","rel":"alternate"}},"published":"2016-05-22T09:30:00+02:00","updated":"2016-05-22T09:30:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-05-22:\/informatik\/pilotos-processes-2-de.html","summary":"<p>In meinem ersten Artikel &uuml;ber Threads stand die konkrete Implementierung im Vordergrund, f&uuml;r diesen Artikel gibt es (noch) keine Implementierung in PilotOS, daher hier etwas Theorie &uuml;ber Prozesse, deren Zust&auml;nde und Blockierung.<\/p>\n<p>Ein Prozess ist eine Einheit der Ausf&uuml;hrung oder Code, der sich in Ausf&uuml;hrung befindet. Bei der Definition spielt \u2026<\/p>","content":"<p>In meinem ersten Artikel &uuml;ber Threads stand die konkrete Implementierung im Vordergrund, f&uuml;r diesen Artikel gibt es (noch) keine Implementierung in PilotOS, daher hier etwas Theorie &uuml;ber Prozesse, deren Zust&auml;nde und Blockierung.<\/p>\n<p>Ein Prozess ist eine Einheit der Ausf&uuml;hrung oder Code, der sich in Ausf&uuml;hrung befindet. Bei der Definition spielt es keine Rolle, ob der Code tats&auml;chlich gerade ausgef&uuml;hrt wird, sondern es gen&uuml;gt, wenn der Code \"bereit\" ist zur Ausf&uuml;hrung, d.h. der Code ist anspringbar, hat Speicher, und k&ouml;nnte theoretisch ausgef&uuml;hrt werden. In realen Betriebssystemen gibt es aber einige Constraints, wann ein Prozess ausgef&uuml;hrt wird. Dazu wurden Prozesszust&auml;nde eingef&uuml;hrt.<\/p>\n<p>Ein Prozesszustand gibt an, in welchem Zustand eines Automaten sich ein Prozess befindet. Ein Prozess kann meist nur dann ausgef&uuml;hrt werden, wenn er sich im Speicher befindet (siehe virtueller Speicher, MMU, Paging), und nicht auf andere Prozesse wartet. Ein Prozess kann beispielsweise dann auf andere Prozesse wechseln, wenn sich der andere Prozess ein Betriebsmittel genommen hat, welches nur exklusiv genutzt werden kann, aber beide Prozesse ben&ouml;tigen.<\/p>\n<p>Betriebsmittel werden vom Betriebssystem verwaltet. Man unterscheide physische und logische BMs. Physisch ist bspw. die Festplatte, der Speicher; logisch eine Datei. Um einen sicheren Zugriff auf Betriebsmittel gibt es in jedem Betriebssystem den gegenseitigen Ausschluss (Mutex, mutual exclusion) um sicherzustellen, dass nur ein Prozess (bzw. genereller nur k Prozesse) einen kritischen Abschnitt ausf&uuml;hren d&uuml;rfen. Ein kritischer Abschnitt ist Code, der, wenn er von mehreren Prozessen nebenl&auml;ufig ausgef&uuml;hrt wird, zu nicht mehr gutzumachendem Schaden im System f&uuml;hren kann.<\/p>\n<p>Es gibt einige Designkritierien f&uuml;r die Implementierung von Mutex. Bspw. Lebendigkeit, d.h. kein Prozess h&auml;lt ein Betriebsmittel unendlich lange, Sicherheit, d.h. etwas nicht mehr gut zu machendes schlechtes darf nicht passieren, Fairness, die unterschiedlich definiert sein kann. Hier nehmen wir folgende Fairness an: kein Prozess muss unendlich lang warten. Anhand dieser Kritieren kann eine Policy implementiert werden, die angibt wie und wann wartende Prozesse freigegeben werden.<\/p>\n<p>Ein Blockieren eines Prozesses kann entweder vom Prozess selbst erfolgen, oder durch das Betriebssystem beim Zugriff auf ein Betriebsmittel. Bspw. ist es manchmal notwendig auf andere Prozesse zu warten, um synchronisiert arbeiten zu k&ouml;nnen. Die erste M&ouml;glichkeit um auf andere Prozesse zu warten ist einen Busy Wait zu implementieren; d.h. eine while-Schleife, die nachschaut, ob die Bedingung, auf die gewartet wird, schon erf&uuml;llt ist. Das ist aber sehr verschwenderisch auf Rechenzeit, weil der Scheduler diesen Prozess weiterhin plant und dieser Prozess sein Zeitintervall nur daf&uuml;r verwendet zu warten.<\/p>\n<p>Sinnvoller w&auml;re es, diesen Prozess nicht mehr zu schedulen bis die Bedingung erf&uuml;llt ist. Dazu setzt man seinen Prozesszustand auf \"wartend\" oder \"blockiert\", was angibt, dass der Prozess auf etwas wartet. Die Bedingung muss ebenfalls gespeichert werden (bspw. in Form eines Mutex-Deskriptors). Wird dieses Mutex (bspw. in Form eines Semaphors implementiert) freigegeben, setzt das Betriebssystem alle darauf wartenden Prozesse in den \"bereit\"-Zustand. Je nachdem, wie viele Prozesse in den kritischen Abschnitt d&uuml;rfen, kann auch nur ein Prozess ausgew&auml;hlt werden, der in den \"bereit\"-Zustand wechselt.<\/p>\n<p>D.h. wir haben grundlegend drei Prozesszust&auml;nde: \"laufend\", d.h. der Prozess wird in diesem Moment von der CPU ausgef&uuml;hrt, \"aktiv\" - der Prozess wartet auf die CPU, kann aber ausgef&uuml;hrt werden und \"blockiert, wartend\" - der Prozess wartet auf Freigabe eines Mutex.<\/p>\n<p>Ein Mutex kann verschiedenen implementiert sein. Es gibt in gew&ouml;hnlichen Betriebssystemen meist eine Semaphor-Implementierung, aber auch Monitore. Alternativ kann das auch durch eine bool'sche Zustandsvariable realisiert werden. Der Trick dabei ist, dass, wenn mehrere Prozesse involviert sind, die Implementierung etwas schwierig ist. So muss beim Eintritt in einen kritischen Abschnitt gepr&uuml;ft werden, ob die Variable gesetzt ist (bzw. die Semaphore einen bestimmten Wert erreicht hat). Falls ja, darf der Prozess nicht in den kritischen Abschnitt und muss warten.<\/p>\n<p>Ist die Variable nicht gesetzt, darf der Prozess in den kritischen Abschnitt, muss aber noch (mit einem zweiten Befehl) die Variable setzen. Wird er jetzt verdr&auml;ngt, kann problemlos ein zweiter Prozess in den kritischen Abschnitt und etwas Schlimmes k&ouml;nnte passieren (siehe Race Condition). Daf&uuml;r haben die meisten Prozessoren einen Befehl, der gleichzeitig eine Variable testen kann, und sie setzt, sodass kein anderer Prozess in den kritischen Abschnitt gelangen kann.<\/p>\n<p>Alternativ k&ouml;nnte f&uuml;r den Zeitraum, in dem sich ein Prozess im kritischen Abschnitt befindet, der Interrupt ausgeschaltet werden. Das h&auml;tte zur Folge, dass der Prozess nicht durch Timer-Interrupts unterbrochen werden kann, aber auch, dass er generell nicht unterbrochen werden kann. Wird diese Methode also angewandt, muss der Programmierer h&ouml;llisch darauf achten, dass sein kritischer Abschnitt sehr kurz ist, um das System nicht unn&ouml;tig auszubremsen, da in dieser Zeit kein anderer Prozess ausgef&uuml;hrt werden kann. Wiederum k&ouml;nnt er die Interrupts auch nur f&uuml;r den Zeitraum deaktivieren, in dem er die Variable testet und setzt, und dann wieder aktivieren.<\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Betriebssystem"}},{"@attributes":{"term":"Blockierung"}},{"@attributes":{"term":"Interprozess-Kommunikation"}},{"@attributes":{"term":"Mutex"}},{"@attributes":{"term":"pilotSO"}},{"@attributes":{"term":"Prozesse"}},{"@attributes":{"term":"Race Condition"}},{"@attributes":{"term":"Zust\u00e4nde"}}]},{"title":"PilotOS: Processes","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/pilotos-processes.html","rel":"alternate"}},"published":"2016-05-21T12:54:00+02:00","updated":"2016-05-21T12:54:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-05-21:\/informatik\/pilotos-processes.html","summary":"<p>PilotOS [1] aims to become a simple operating system for the Raspberry Pi. I use it mainly to learn the ins and outs of operating system development, starting with simple functionality all the way to operating system architecture. In no way is PilotOS meant to be a usable operating system \u2026<\/p>","content":"<p>PilotOS [1] aims to become a simple operating system for the Raspberry Pi. I use it mainly to learn the ins and outs of operating system development, starting with simple functionality all the way to operating system architecture. In no way is PilotOS meant to be a usable operating system of any description, it's just for playing around.<\/p>\n<p>Yesterday I added processes and a simple scheduler and dispatcher to the mix. A dispatcher is the functionality for switching between processes, i.e. it has to jump between the processes and save and restore the context of the process. Scheduling is more like a policy on how the next process is chosen.<\/p>\n<p>There is cooperative and preemptive scheduling. With cooperating scheduling the process will yield the control over the CPU itself, either by calling a specific function or sometimes by calling any system call. Some operating systems did implement it in a way, that every system call is used for switching between processes. Preemptive scheduling uses a timer interrupt for the preemption of processes. I.e. at start of the system the timer will be programmed to deliver and interrupt after a certain amount of time. The interrupt will be caught by the CPU and handled by an interrupt service routine (ISR). The ISR will start the dispatching. This also means, that a process can be preempted at any point in time (see race conditions).<\/p>\n<p>I implemented at first a cooperative switching. Well to be more precise: I implemented the framework for cooperating switching and didn't even bother testing it yet. The code is not used yet, so there is no dispatching and there are no processes yet.<\/p>\n<p>The scheduler uses a comparison-function for choosing the next process. This function returns for two process-control-block (PCB) one, that it finds useful for any criterion it is set out to compare for. The schedule-routine is only there for applying the comparison-function to every PCB in the system. A PCB contains information about a process, in this example an ID, deadline, execution-time, last-use-information and the stack-pointer. Not all of these attributes are used usefully (yet).<\/p>\n<p>The yielding of the CPU works with the function <em>yield<\/em>, which is jumping directly into the function <em>dispatch<\/em>. The separation of these two function is currently not useful, but maybe later on I'll find it useful that I split these two functions up. The dispatcher saves the Link-register (<em>lr<\/em>) onto the stack. The Link-register in ARM saves the return-address after a function call (linked branch) has occured (assembler instruction <em>bl<\/em>). In the called function there is the link register, which can be used with the instruction <em>mov pc, lr<\/em> to return to the caller-code. (PC - Program Counter, Instruction Pointer).<\/p>\n<p>Then all registers from r1 to r12 will be saved onto the stack. r13, r14 and r15 will not be saved for they have special functionality in the ARM-core. r13 is the stack-pointer. Saving this onto the stack would be quite useless. r14 is used as the link register. One could argue, that it might be helping to save this register with all the others, but then I would have to know, whether <em>push<\/em> and <em>pop<\/em> can save all the registers in one instruction, or maybe the Assembler will split the instruction into several ones up, which only save one register at a time. Saving r15, the program counter, onto the stack is completely bogus. The program counter points into the <em>dispatch<\/em>-function at the moment, restoring that program-counter would lead to us not being able to leave the dispatch function ever.<\/p>\n<p>After saving all these registers I can use them for calculations without risking loosing all of the values a process may have saved in them. But we still need to store the stack-pointer of the yielding process in our PCB, then we can load the addresses of the comparison-functions in r0 and r1 and call the <em>schedule<\/em>-function. Its result is stored in r0. Now I need to change the stack-pointer of the CPU, recovering the old one of the next process. Every saved register is pop'd from the stack. At last the link-register is pop'd from the stack, but it will be saved into the pc-register. So the next instruction executed will be the next one of the chosen process.<\/p>\n<p>[1] <a href=\"https:\/\/github.com\/naums\/pilotOS\">https:\/\/github.com\/naums\/pilotOS<\/a><\/p>\n<p>Content-Image: <a href=\"https:\/\/openclipart.org\/detail\/175363\/pilot-penguin\">https:\/\/openclipart.org\/detail\/175363\/pilot-penguin<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"context"}},{"@attributes":{"term":"context-switch"}},{"@attributes":{"term":"Dispatch"}},{"@attributes":{"term":"job"}},{"@attributes":{"term":"Operating System"}},{"@attributes":{"term":"PilotOS"}},{"@attributes":{"term":"process"}},{"@attributes":{"term":"Schedule"}},{"@attributes":{"term":"Task"}}]},{"title":"PilotOS: Prozesse","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/pilotos-processes-de.html","rel":"alternate"}},"published":"2016-05-21T12:14:00+02:00","updated":"2016-05-21T12:14:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-05-21:\/informatik\/pilotos-processes-de.html","summary":"<p>PilotOS [1] soll ein einfaches Betriebssystem f&uuml;r den Raspberry Pi werden. Der Sinn hinter dem Betriebssystem ist haupts&auml;chlich der Wissenszuwachs f&uuml;r mich, und die Einblicke in die Entwicklung von Betriebssystem, angefangen von einfachen Funktionalit&auml;ten, bis hin zur Architektur von Betriebssystemen. PilotOS zielt dabei in keinster Weise auf Benutzbarkeit, sondern dient \u2026<\/p>","content":"<p>PilotOS [1] soll ein einfaches Betriebssystem f&uuml;r den Raspberry Pi werden. Der Sinn hinter dem Betriebssystem ist haupts&auml;chlich der Wissenszuwachs f&uuml;r mich, und die Einblicke in die Entwicklung von Betriebssystem, angefangen von einfachen Funktionalit&auml;ten, bis hin zur Architektur von Betriebssystemen. PilotOS zielt dabei in keinster Weise auf Benutzbarkeit, sondern dient einzig und allein den Spielerei-Zwecken.<\/p>\n<p>Gestern habe ich Prozesse hinzugef&uuml;gt und einen einfachen Scheduler sowie Dispatcher f&uuml;r Prozesse. Ein Dispatcher ist daf&uuml;r da, Prozesse umzuschalten, d.h. die CPU anzuweisen in einen anderen Prozess zu springen, sowie dessen Kontext wiederherzustellen, nachdem der Kontext des verdr&auml;ngten Prozess abgespeichert worden ist. Scheduling stellt die Strategie dar, nach welcher der n&auml;chste Prozess gew&auml;hlt wird.<\/p>\n<p>Es gibt sowohl kooperatives als auch preemptives Umschalten. Beim kooperativen Umschalten geben die Prozesse ihre Kontrolle &uuml;ber die CPU freiwillig ab, bspw. durch Rufen einer bestimmten Funktion. Manchmal ist das auch so implementiert, dass jeder Systemruf dazu f&uuml;hrt, dass umgeschalten werden kann. Preemptives Umschalten wird durch Timer-Interrupts realisiert. D.h. beim Start des Systems wird der Hardware-Timer auf eine bestimmte Zeit programmiert, nach der er einen Interrupt ausl&ouml;sen soll. Dieser Interrupt wird von der CPU gefangen, und in einer bestimmten Interrupt Service Routine (ISR) verarbeitet. Diese ISR sorgt dann f&uuml;r das Umschalten. Das hat zur Folge, dass jeder Prozess zu jedem Zeitpunkt umgeschalten werden kann (siehe Race Conditions).<\/p>\n<p>In PilotOS ist aktuell ein kooperatives Umschalten implementiert. Genau genommen steht erst einmal nur die M&ouml;glichkeit f&uuml;r kooperatives Umschalten. Der Code wird aktuell noch nirgends verwendet, und ist noch ungetestet. Der Scheduler w&auml;hlt einen Prozess aus, mithilfe einer Vergleichfunktion, die anhand irgendeines beliebigen Merkmals aus zwei Prozessen (bzw. Prozess-Kontroll-Bl&ouml;cken, PCB) einen zur&uuml;ck liefert. Die eigentliche Scheduling-Routine wendet diese Funktion also auf alle PCBs an. Ein PCB beinhaltet Informationen &uuml;ber die Prozesse, hier sind das Informationen wie ID, Deadline, Execution-Time, Last-Use-Informationen und der StackPointer. Nicht alle Attribute werden aktuell (sinnvoll) eingesetzt.<\/p>\n<p>Zum Abgeben der Kontrolle der CPU gibt es die Funktion <em>yield<\/em>, die direkt in die Funktion <em>dispatch<\/em> springt. Die Trennung der beiden Funktionen ist aktuell unn&ouml;tig, kann aber eventuell sp&auml;ter n&uuml;tzlich sein, daher habe ich das erst einmal so implementiert. Der Dispatcher speichert sich das Link-Register (lr) auf dem Stack. Das Link-Register gibt bei ARM die R&uuml;cksprungaddresse an, nach einem Link-Branch (Assembler-Befehl <em>bl<\/em>), der eine Art Funktionsaufruf darstellt. In der aufgerufenen Funktion steht dann das Link-Register auf dem n&auml;chsten Befehl, in dem Code vor dem Funktionsruf, d.h. mithilfe von <em>mov pc, lr<\/em> l&auml;sst sich wieder zur&uuml;ckspringen (PC - Program Counter, Instruction Pointer).<\/p>\n<p>Dann werden alle Register (r1,..r12) gespeichert. r13, r14, r15 werden nicht mit abgespeichert, weil diese besondere Funktionen im ARM-Kern haben. r13 ist der Stackpointer - den auf den Stack weg zu speichern w&auml;re relativ sinnlos. r14 ist das Link-Register. Man k&ouml;nnt &uuml;berlegen, ob es Sinn machen w&uuml;rde, dieses Register zusammen mit den anderen abzuspeichern - dazu m&uuml;sst ich mir die Semantik von <em>push<\/em> und <em>pop<\/em> genauer zu Gem&uuml;te f&uuml;hren. Vor allem m&uuml;sst gekl&auml;rt werden, inwiefern die Befehle die Register gleichzeitig speichern und laden, oder ob der Befehl vom Assembler in mehrere kleinere Befehle zerteilt wird. Den Programm-Counter (r15) auf dem Stack zu speichern ist komplett sinnlos, weil der aktuell in der <em>dispatch<\/em>-Funktion steckt. Den abzuspeichern, und wieder zu laden w&uuml;rde verhindern, dass wir diese Funktion jemals wieder verlassen.<\/p>\n<p>Nachdem die Register abgespeichert sind, k&ouml;nnen sie verwendet werden, ohne riskieren zu m&uuml;ssen, dass Werte des eigentlichen Prozesses verloren gehen. Zun&auml;chst m&uuml;ssen wir aber den Stackpointer des verdr&auml;ngten Prozesses in den PCB schreiben. Nun lade ich die Adressen der Funktionen, die von der <em>schedule<\/em>-Funktion benutzt werden sollen, um den n&auml;chsten Prozess zu finden und rufe die Funktion. Das Ergebnis liegt in r0. Nun muss nur der Stackpointer umgesetzt und die zuvor gespeicherten Register wieder geladen werden. Zum Schluss hole ich dann das Link-Register noch vom Stack, allerdings speichere das Ergebnis im Program-Counter, sodass der n&auml;chste ausgef&uuml;hrte Befehl der n&auml;chste Befehl des Prozesses ist, der nun ausgef&uuml;hrt werden soll.<\/p>\n<p>[1] <a href=\"https:\/\/github.com\/naums\/pilotOS\">https:\/\/github.com\/naums\/pilotOS<\/a><\/p>\n<p>Beitragsbild: <a href=\"https:\/\/openclipart.org\/detail\/175363\/pilot-penguin\">https:\/\/openclipart.org\/detail\/175363\/pilot-penguin<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Activity"}},{"@attributes":{"term":"Betriebssystem"}},{"@attributes":{"term":"Dispatch"}},{"@attributes":{"term":"Jobs"}},{"@attributes":{"term":"Kontext"}},{"@attributes":{"term":"Kontextwechsel"}},{"@attributes":{"term":"Operating System"}},{"@attributes":{"term":"PilotOS"}},{"@attributes":{"term":"Prozesse"}},{"@attributes":{"term":"Raspberry Pi"}},{"@attributes":{"term":"Schedule"}},{"@attributes":{"term":"Task"}}]},{"title":"Odyssee durch Debian-Linuxe","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/odyssee-durch-debian-linuxe.html","rel":"alternate"}},"published":"2016-05-14T08:47:00+02:00","updated":"2016-05-14T08:47:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-05-14:\/informatik\/odyssee-durch-debian-linuxe.html","summary":"<p>Wie einige sicher schon wissen wurde vor einigen Wochen die neue LTS von Ubuntu ver&ouml;ffentlicht 16.04. Eine LTS stellt in der Regel im Ubuntu-Universum eine besonders stabile Version dar, die &uuml;ber einen sehr langen Zeitraum unterst&uuml;tzt wird und mit Aktualisierungen versorgt wird. Wenn man sich Linux Mint anschaut, ist \u2026<\/p>","content":"<p>Wie einige sicher schon wissen wurde vor einigen Wochen die neue LTS von Ubuntu ver&ouml;ffentlicht 16.04. Eine LTS stellt in der Regel im Ubuntu-Universum eine besonders stabile Version dar, die &uuml;ber einen sehr langen Zeitraum unterst&uuml;tzt wird und mit Aktualisierungen versorgt wird. Wenn man sich Linux Mint anschaut, ist diese Distribution auf dem Stand der letzten LTS 14.04 stehen geblieben, was auch vor dem Hintergrund Sinn ergibt, dass alle anderen Versionen nur noch 9 Monate lang unterst&uuml;tzt werden.<\/p>\n<p>Ich habe also meine Rechner von Linux Mint 17 auf Xubuntu 16.04 aktualisiert. Da gibt es ein (bekanntes) Problem: Die fglrx-AMD-Grafikkartentreiber werden nicht angeboten, weil die aktuell mit dem aktuellen Xorg-Server nicht funktionieren. Was genau ist am aktuellen Xorg bitte so wichtig, dass man die Grafikbeschleunigung von quasi einem drittel der Nutzer in die Tonne tritt? Und h&auml;tte man die Xorg-Aktualisierung nicht aktualisieren k&ouml;nnen, wenn AMD die Grafiktreiber nachliefert, die mit dem aktuellen Xorg funktionieren? Aber macht auch nichts, weil der verwendete Kernel ist offenbar auch zu aktuell um mit den AMD-Treibern zu funktionieren. Das ist &uuml;brigens kein Problem von Ubuntu, sondern von allen Linux-Distributionen, auch bspw. Debian testing.<\/p>\n<p>Au&szlig;erdem gibt es einige Probleme mit ffmpeg, namentlich, dass der Hauppage HD PVR [4] (von anderen Ger&auml;ten wei&szlig; ich das nicht) nicht mehr zum streamen ge&ouml;ffnet werden kann. Der Umweg &uuml;ber 'cat \/dev\/video0 &gt; test.mp4' funktioniert aber problemlos. Da Open Broadcaster Software Studio auf ffmpeg aufbaut, macht sich gerade der Fehler nicht gut.<\/p>\n<p>Ich k&ouml;nnte ja auch auf Linux Mint 17 stehen bleiben, da funktionert fglrx, ffmpeg-next [1] und damit auch obs-studio. Aber dann habe ich das Problem, dass ich auf einem uralten (&uuml;ber zwei Jahre) KDEnlive arbeiten muss. KDEnlive ist ein freier nicht-linearer Videoeditor, den ich zur Erstellung meiner Videos benutze. Die uralte Version l&auml;sst sich dank fehlendem KDE5 nicht unter Mint 17 aktualisieren. Au&szlig;erdem sind in der Version ebenfalls einige richtig fiese Bugs, die das Projekt zerst&ouml;ren wenn man es mit 60fps erstellen will.<\/p>\n<p>Also gut. Installier ich halt Debian 8, da m&uuml;sste fglrx gehen, weil uralter Xorg, und KDEnlive kann ich mir zur Not aus den testing-Quellen nachinstallieren - in der Hoffnung er aktualisiert den Xorg nicht mit. Siehe da! fglrx funktioniert problemlos. Aber... Debian bietet nur die avconv-tools an und nicht ffmpeg. avconv und ffmpeg sind grunds&auml;tzlich eigentlich die gleichen Programme, sie haben sich irgendwann 2011 gespalten (fork) und haben ab da eine getrennte Entwicklung genossen. Zwar kenne ich mich mit den Unterschiedenen der beiden Programme nicht aus, aber die Bedienung in der Shell sieht noch recht gleich aus. Warum obs-studio dann unbedingt ffmpeg voraussetzt, bleibt mir ein R&auml;tsel.<\/p>\n<p>Hinzu kommt, dass Debian nat&uuml;rlich keine Ubuntu PPAs unterst&uuml;tzt, und damit auch nicht, dass man einfach mal den ffmpeg-next aus dem Repository nachinstalliert. Das hei&szlig;t selbst bauen [2]. Nach der Anleitung also selbst gebaut, und schwubbs! Gleicher Fehler wie unter Ubuntu - ist ja klar, weil der Fehler sicher nicht von der Distribution abh&auml;ngig ist. Theoretisch h&auml;tte ich mir eine &auml;ltere Version bauen k&ouml;nnen - r&uuml;ckwirkend betrachtet w&auml;re das auch durchaus sinnvoll gewesen - aber naja.<\/p>\n<p>KDEnlive aus den testing Quellen zu installieren habe ich dann aber gar nicht mehr probiert.<\/p>\n<p>Mein Streaming-PC wird jetzt, bis ein Fix da ist, oder f&uuml;r immer, das alte Linux Mint 17 benutzen. Auf meinem Laptop versuche ich mich jetzt an Arch-Linux, damit ich auf lange Sicht von Ubuntu wegkomme. Neben den oben genannten Problemen hat Ubuntu noch einige andere mit Programmstabilit&auml;t. Bspw. wollten sich einige Einstellungs-Programme &uuml;berhaupt nicht zeigen, was etwas merkw&uuml;rdig ist, bei einer Distribution, die doch so auf Nutzerfreundlichkeit ausgelegt ist. Mein Fix war da &uuml;brigens den Crash-Reporter zu deinstallieren, damit der wenigstens nicht mehr nervt.<\/p>\n<p>Arch-Linux hat auch die Probleme mit ffmpeg, und Arch-Linux hat auch die Probleme mit fglrx. Aber mein Laptop muss (a) den Hauppauge HD PVR nicht mit ffmpeg &ouml;ffnen, weil auf dem dank fehlendem OpenGL 3.1 (?) ohnehin kein obs-studio l&auml;uft. (b) hat der Laptop keine AMD-Grafikkarte, sondern eine Intel HD 3000, die theoretisch ohne propriet&auml;ren Treiber von Xorg problemlos unterst&uuml;tzt wird.<\/p>\n<p>Zum Abschluss noch einige polemische Fragen: Warum setzen Programme wie obs-studio oder ScreenStudio [3] auf ffmpeg und kommen mit avconv nicht klar. Wie kann ich als Distributor auf AMD-Grafikkarten-Unterst&uuml;tzung verzichten? Ja, es gibt radeon, der aber eher schlecht als recht funktioniert, aber immerhin Grafikbeschleunigung f&uuml;r den Desktop bringt. Daf&uuml;r hat der VLC bspw. beim Screenshots von Videos machen Probleme mit radeon. Gibt es einen Grund daf&uuml;r, warum Debian ausschlie&szlig;lich avconv mitliefert und nicht ffmpeg mit? Warum biegen die nicht cmake-Regeln, Pfade, Programmnamen (siehe Alias) um, sodass der Name ffmpeg auf avconv verwei&szlig;t?<\/p>\n<p>Ich hoffe, dass ich mit Arch-Linux als erster von einem ffmpeg-Fix profitiere.<\/p>\n<p>[1] <a href=\"https:\/\/launchpad.net\/~kirillshkrogalev\/+archive\/ubuntu\/ffmpeg-next\">https:\/\/launchpad.net\/~kirillshkrogalev\/+archive\/ubuntu\/ffmpeg-next<\/a><br\/>\n[2] <a href=\"https:\/\/trac.ffmpeg.org\/wiki\/CompilationGuide\/Ubuntu\">https:\/\/trac.ffmpeg.org\/wiki\/CompilationGuide\/Ubuntu<\/a><br\/>\n[3] <a href=\"http:\/\/screenstudio.crombz.com\/\">http:\/\/screenstudio.crombz.com\/<\/a><br\/>\n[4] <a href=\"http:\/\/www.hauppauge.de\/site\/products\/data_hdpvr.html\">http:\/\/www.hauppauge.de\/site\/products\/data_hdpvr.html<\/a><\/p>\n<p>Beitragsbild: <a href=\"http:\/\/www.larysa-golik.de\/bildergalerie\/illustrationen\/grafx\/odyssee\/06-odyssee.jpg\">http:\/\/www.larysa-golik.de\/bildergalerie\/illustrationen\/grafx\/odyssee\/06-odyssee.jpg<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"arch"}},{"@attributes":{"term":"avconv"}},{"@attributes":{"term":"ffmpeg"}},{"@attributes":{"term":"fglrx"}},{"@attributes":{"term":"HD PVR"}},{"@attributes":{"term":"linux"}},{"@attributes":{"term":"MINT"}},{"@attributes":{"term":"obs-studio"}},{"@attributes":{"term":"stream"}},{"@attributes":{"term":"ubuntu"}},{"@attributes":{"term":"xenial"}}]},{"title":"Studierendensymposium Informatik 2016: Automatisierte Verl\u00e4sslichkeitsmodelle verteilter Anwendungen","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/studierendensymposium-informatik-2016-automatisierte-verlaesslichkeitsmodelle-verteilter-anwendungen.html","rel":"alternate"}},"published":"2016-05-08T14:58:00+02:00","updated":"2016-05-08T14:58:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-05-08:\/informatik\/studierendensymposium-informatik-2016-automatisierte-verlaesslichkeitsmodelle-verteilter-anwendungen.html","content":"<p>Am Donnerstag 28.04.2016 waren die Vortr&auml;ge f&uuml;r das Studierendensymposium 2016 der Fakult&auml;t Informatik an der TU Chemnitz. Dabei habe ich einen Vortrag &uuml;ber das Thema meiner Bachelorarbeit gehalten: (Automatisierte) Verl&auml;sslichkeitsmodelle verteilter Anwendungen. Unten sind die Vortragsfolien herunterzuladen.<\/p>\n<p><a href=\"\/static\/resources\/2016-11-verl&auml;sslichkeitsmodelle_presentation.pdf\">Vortragsfolien<\/a><\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"MySQL\/MariaDB in Haskell","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/mysqlmariadb-in-haskell.html","rel":"alternate"}},"published":"2016-04-01T20:42:00+02:00","updated":"2016-04-01T20:42:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-04-01:\/informatik\/mysqlmariadb-in-haskell.html","summary":"<p>Seit einer Weile \"arbeite\" ich daran ein mittelgro&szlig;es Projekt in Haskell zu implementieren. Heute habe ich mich dazu mit der Datenbankanbindung besch&auml;ftigt. Dazu gibt es in Haskell HDBC [1]. HDBC erlaubt es euch, zusammen mit einem Driver f&uuml;r die entsprechende Datenbank einer Datenbank SQL-Anfragen zu stellen. Theoretisch soll sogar das \u2026<\/p>","content":"<p>Seit einer Weile \"arbeite\" ich daran ein mittelgro&szlig;es Projekt in Haskell zu implementieren. Heute habe ich mich dazu mit der Datenbankanbindung besch&auml;ftigt. Dazu gibt es in Haskell HDBC [1]. HDBC erlaubt es euch, zusammen mit einem Driver f&uuml;r die entsprechende Datenbank einer Datenbank SQL-Anfragen zu stellen. Theoretisch soll sogar das Wechseln der Datenbank ziemlich schmerzlos funktionieren. HDBC an sich kann &uuml;ber die Paketquellen auf Raspbian installiert werden.<\/p>\n<p>Das erste Problem ist allerdings HDBC-mysql zu installieren. Ich verwende dazu einen Raspberry Pi 3 mit Raspbian 8 Jessie. ghc existiert daf&uuml;r zwar, aber es gibt keinen interaktiven Modus.<\/p>\n<p>Zum Installieren von Paketen in Haskell gibt es das Tool <em>cabal<\/em> [2],[3]. Dh. als erstes muss das Paket '<em>cabal-install<\/em>' mit <em>apt-get<\/em> nachinstalliert werden. Theoretisch sollte das Tool in der Lage sein, Pakete automatisch herunterzuladen und zu installieren, wenn ihr einen Namen eingebt. Dazu m&uuml;sstet ihr dem Tool mitteilen, dass es ein Update seiner internen Datenbank machen soll. Als Repository verwendet das Tool standardm&auml;&szlig;ig <em>hackage<\/em>. Daf&uuml;r hatten aber etwa 500 MB freier Arbeitsspeicher nicht mehr gereicht, nachdem das Tool also RAM und Swap vollgeschrieben hatte, wurde es w&auml;hrend des Updatens von Linux beendet.<\/p>\n<p>Danach meinte das Tool zwar, dass die entfernten und die lokalen Daten &uuml;bereinstimmen HDBC-mysql konnte ich so aber dennoch nicht herunterladen. Also habe ich mich auf die Suche nach den Quellen dieses Pakets gemacht und unter [4] gefunden. Das Repository zu klonen und zu installieren hatte nicht funktioniert, also habe ich mir das letzte Release 0.6.6.1 heruntergeladen und entpackt.<\/p>\n<p>Im Archiv enthalten ist unter anderem eine <em>Setup.lhs<\/em> und eine <em>HDBC-mysql.cabal<\/em>-Datei. Auf letztere kann ich dann endlich <em>cabal<\/em> anwenden:<\/p>\n<blockquote>\n<p>cabal install HDCB-mysql.cabal<\/p>\n<\/blockquote>\n<p><em>cabal<\/em> lief nun problemlos durch und hat das Paket installiert. Nun kann HDBC-mysql benutzt werden. Folgender Code dient mir daf&uuml;r als Testcode:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kr\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">Control.Monad<\/span><span class=\"w\"> <\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"kr\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">Database.HDBC<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"kr\">import<\/span><span class=\"w\"> <\/span><span class=\"nn\">Database.HDBC.MySQL<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nf\">myshow<\/span><span class=\"w\"> <\/span><span class=\"ow\">::<\/span><span class=\"w\"> <\/span><span class=\"p\">[[<\/span><span class=\"kt\">SqlValue<\/span><span class=\"p\">]]<\/span><span class=\"w\"> <\/span><span class=\"ow\">-&gt;<\/span><span class=\"w\"> <\/span><span class=\"kt\">IO<\/span><span class=\"nb\">()<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">myshow<\/span><span class=\"w\"> <\/span><span class=\"kt\">[]<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">return<\/span><span class=\"w\"> <\/span><span class=\"nb\">()<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">myshow<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"kt\">:<\/span><span class=\"n\">xs<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"kr\">do<\/span><span class=\"w\"> <\/span><span class=\"n\">putStrLn<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Hello\"<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                   <\/span><span class=\"n\">myshow2<\/span><span class=\"w\"> <\/span><span class=\"n\">x<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                   <\/span><span class=\"n\">myshow<\/span><span class=\"w\"> <\/span><span class=\"n\">xs<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nf\">myshow2<\/span><span class=\"w\"> <\/span><span class=\"ow\">::<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"kt\">SqlValue<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"ow\">-&gt;<\/span><span class=\"w\"> <\/span><span class=\"kt\">IO<\/span><span class=\"nb\">()<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">myshow2<\/span><span class=\"w\"> <\/span><span class=\"kt\">[]<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">return<\/span><span class=\"w\"> <\/span><span class=\"nb\">()<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">myshow2<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">x<\/span><span class=\"kt\">:<\/span><span class=\"n\">xs<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"kr\">do<\/span><span class=\"w\"> <\/span><span class=\"n\">putStrLn<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">show<\/span><span class=\"w\"> <\/span><span class=\"n\">x<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                    <\/span><span class=\"n\">myshow2<\/span><span class=\"w\"> <\/span><span class=\"n\">xs<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nf\">main<\/span><span class=\"w\"> <\/span><span class=\"ow\">::<\/span><span class=\"w\"> <\/span><span class=\"kt\">IO<\/span><span class=\"nb\">()<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">main<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"kr\">do<\/span><span class=\"w\"> <\/span><span class=\"n\">conn<\/span><span class=\"w\"> <\/span><span class=\"ow\">&lt;-<\/span><span class=\"w\"> <\/span><span class=\"n\">connectMySQL<\/span><span class=\"w\"> <\/span><span class=\"n\">defaultMySQLConnectInfo<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"w\"> <\/span><span class=\"n\">mysqlHost<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"127.0.0.1\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mysqlUser<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"test\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mysqlPassword<\/span><span class=\"w\"> <\/span><span class=\"ow\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"t3stpasswort\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">mysqlDatabase<\/span><span class=\"ow\">=<\/span><span class=\"s\">\"oettingergames\"<\/span><span class=\"w\"> <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span><span class=\"n\">rows<\/span><span class=\"w\"> <\/span><span class=\"ow\">&lt;-<\/span><span class=\"w\"> <\/span><span class=\"n\">quickQuery'<\/span><span class=\"w\"> <\/span><span class=\"n\">conn<\/span><span class=\"w\"> <\/span><span class=\"s\">\"SELECT * FROM game\"<\/span><span class=\"w\"> <\/span><span class=\"kt\">[]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span><span class=\"n\">myshow<\/span><span class=\"w\"> <\/span><span class=\"n\">rows<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><em>quickQuery<\/em> liefert <em>[[SqlValue]]<\/em> zur&uuml;ck, dh. eine Liste von Listen von <em>SqlValue<\/em>. Die inneren Listen deuten jeweils einen Datensatz an, dh. jedes Element einer inneren Liste ist eine Spalte in der Relation. Die &auml;u&szlig;ere Liste umfasst also alle abgefragten Datens&auml;tze.<\/p>\n<p>[1] <a href=\"https:\/\/hackage.haskell.org\/package\/HDBC-mysql\">https:\/\/hackage.haskell.org\/package\/HDBC-mysql<\/a><br\/>\n[2] <a href=\"https:\/\/www.haskell.org\/cabal\/\">https:\/\/www.haskell.org\/cabal\/<\/a><br\/>\n[3] <a href=\"https:\/\/www.haskell.org\/cabal\/users-guide\/\">https:\/\/www.haskell.org\/cabal\/users-guide\/<\/a><br\/>\n[4] <a href=\"https:\/\/github.com\/bos\/hdbc-mysql\">https:\/\/github.com\/bos\/hdbc-mysql<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"haskell"}},{"@attributes":{"term":"hdbc"}},{"@attributes":{"term":"mariadb"}},{"@attributes":{"term":"mysql"}}]},{"title":"ChibiOS\/RT f\u00fcr Raspberry Pi","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/chibiosrt-fuer-raspberry-pi.html","rel":"alternate"}},"published":"2016-03-17T15:00:00+01:00","updated":"2016-03-17T15:00:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2016-03-17:\/informatik\/chibiosrt-fuer-raspberry-pi.html","summary":"<p>Hallo.<\/p>\n<p>ChibiOS\/RT [1] ist ein sehr kleines Realtime-Operating System. Es unterst&uuml;tzt Plattformen, die Linux bspw. nicht mehr abdeckt und kann f&uuml;r allerlei Spielerei benutzt werden. ChibiOS\/RT kann keine Prozesse zur Laufzeit erstellen oder nachladen, Programme f&uuml;r das System m&uuml;ssen in den Betriebssystemkern eingebaut werden. Ich habe versucht die \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>ChibiOS\/RT [1] ist ein sehr kleines Realtime-Operating System. Es unterst&uuml;tzt Plattformen, die Linux bspw. nicht mehr abdeckt und kann f&uuml;r allerlei Spielerei benutzt werden. ChibiOS\/RT kann keine Prozesse zur Laufzeit erstellen oder nachladen, Programme f&uuml;r das System m&uuml;ssen in den Betriebssystemkern eingebaut werden. Ich habe versucht die Anleitung unter [2] nachzuvollziehen, um ChibiOS\/RT f&uuml;r den Raspberry Pi zu bauen. Meine Plattform: Linux Mint 17.1 Rebecca. Weil ich damit hinreichend gro&szlig;e Probleme hatte, erl&auml;utere ich hier, was aktuell ein valides Vorgehen ist um den Betriebssystemkern zu bauen.<\/p>\n<h3 id=\"was-wird-benotigt\">Was wird ben&ouml;tigt?<\/h3>\n<p>Ihr ben&ouml;tigt folgende Software:<\/p>\n<ul>\n<li><em>arm-none-eabi-gcc<\/em> Cross-Compiler, am Besten aus [3]<\/li>\n<li><em>git<\/em><\/li>\n<li><em>screen<\/em><\/li>\n<\/ul>\n<p>Folgende Hardware wird ben&ouml;tigt:<\/p>\n<ul>\n<li>Raspberry Pi<\/li>\n<li>Adafruit TTL-USB-Kabel [4]<\/li>\n<\/ul>\n<h3 id=\"vorgehen\">Vorgehen<\/h3>\n<p>Zun&auml;chst wird ein passender Compiler gebraucht. Es ist offenbar m&ouml;glich das Betriebssystem auf dem Pi selbst zu bauen, ich habe das Betriebssystem auf einem x86-Rechner gebaut. Dazu wird ein Cross Compiler ben&ouml;tigt. Ein Cross Compiler ist ein Compiler, der auf einer Plattform l&auml;uft (hier x86), aber Programme f&uuml;r eine andere Plattform erzeugt (hier ARMv6). Den <em>arm-none-eabi<\/em> aus den Paketquellen hatte ich verwendet (das war eine 4.8.1), das hat aber nicht funktioniert. Das reparieren von internen Headerfiles hatte ich mich nicht lange angetan.<\/p>\n<p>Daher lieber den Compiler von [3] nehmen, der wird offenbar von ARM-Mitarbeitern gepflegt, und funktioniert. Au&szlig;erdem ist das eine 5.2.1. Probiert nun aus, ob der Compiler gefunden wird, bspw. so: <em>arm-none-eabi-gcc --version .<\/em><\/p>\n<p>Als n&auml;chstes braucht ihr den ChibiOS\/RT Quellcode. Ich habe den recht veralteten Code aus dem Artikel genommen, der ein vorbereitetes Makefile f&uuml;r den Pi zu bieten hat. Im offiziellen Code habe ich das nicht gefunden. Zum Laden des Quellcodes wird <em>git<\/em> ben&ouml;tigt.&nbsp;<code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">git clone https:\/\/github.com\/steve-bate\/ChibiOS-RPi<\/code><\/p>\n<p>Nun navigiert ihr in das Verzeichnis <em>demos\/ARM11-BCM2835-GCC\/<\/em> und ruft&nbsp;<em>make<\/em>. Wenn alles gut geht, solltet ihr jetzt im <em>build<\/em>-Ordner eine Datei namens <em>ch.bin<\/em> haben. Kopiert diese Datei auf eine SD-Karte mit dem Namen <em>kernel.img<\/em>, wo bereits ein Raspbian installiert ist. Die alte <em>kernel.img<\/em> solltet ihr sicherheitshalber kopieren, wenn ihr das Linux wieder benutzen wollt.<\/p>\n<p>F&uuml;r die Kommunikation mit ChibiOS\/RT wird eine serielle Verbindung ben&ouml;tigt, bspw. mit dem Adafruit TTL-Kabel [4]. Verbindet das Kabel wie unter [5] dargestellt. Startet in einem Terminal die serielle Konsole:&nbsp;<code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">sudo screen \/dev\/ttyUSB0 115200<\/code><\/p>\n<p>Schaltet den Pi an, indem ihr entweder das rote Kabel an den GPIO-Pin anschlie&szlig;t, oder das Stromkabel des Pi an den Micro-USB-Anschluss. Ihr solltet im Terminalfenster die Kommandozeile von ChibiOS\/RT vorfinden. Mit dem Befehl <em>help<\/em> listet euch das Betriebssystem die (wenigen) Befehle auf.<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"nv\">ChibiOS<\/span><span class=\"o\">\/<\/span><span class=\"nv\">RT<\/span><span class=\"w\"> <\/span><span class=\"nv\">Shell<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"nv\">ch<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"nv\">help<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">Commands<\/span>:<span class=\"w\"> <\/span><span class=\"nv\">help<\/span><span class=\"w\"> <\/span><span class=\"k\">exit<\/span><span class=\"w\"> <\/span><span class=\"nv\">info<\/span><span class=\"w\"> <\/span><span class=\"nv\">systime<\/span><span class=\"w\"> <\/span><span class=\"nv\">reboot<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">ch<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"nv\">info<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">Kernel<\/span>:<span class=\"w\">       <\/span><span class=\"mi\">2<\/span>.<span class=\"mi\">5<\/span>.<span class=\"mi\">1<\/span><span class=\"nv\">unstable<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">Compiler<\/span>:<span class=\"w\">     <\/span><span class=\"nv\">GCC<\/span><span class=\"w\"> <\/span><span class=\"mi\">5<\/span>.<span class=\"mi\">2<\/span>.<span class=\"mi\">1<\/span><span class=\"w\"> <\/span><span class=\"mi\">20151202<\/span><span class=\"w\"> <\/span><span class=\"ss\">(<\/span><span class=\"nv\">release<\/span><span class=\"ss\">)<\/span><span class=\"w\"> <\/span>[<span class=\"nv\">ARM<\/span><span class=\"o\">\/<\/span><span class=\"nv\">embedded<\/span><span class=\"o\">-<\/span><span class=\"mi\">5<\/span><span class=\"o\">-<\/span><span class=\"nv\">branch<\/span><span class=\"w\"> <\/span><span class=\"nv\">revision<\/span><span class=\"w\"> <\/span><span class=\"mi\">231848<\/span>]<\/span>\n<span class=\"code-line\"><span class=\"nv\">Architecture<\/span>:<span class=\"w\"> <\/span><span class=\"nv\">ARM11<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">Core<\/span><span class=\"w\"> <\/span><span class=\"nv\">Variant<\/span>:<span class=\"w\"> <\/span><span class=\"nv\">ARM1176JZF<\/span><span class=\"o\">-<\/span><span class=\"nv\">S<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">Port<\/span><span class=\"w\"> <\/span><span class=\"nv\">Info<\/span>:<span class=\"w\">    <\/span><span class=\"nv\">Pure<\/span><span class=\"w\"> <\/span><span class=\"nv\">ARM<\/span><span class=\"w\"> <\/span><span class=\"nv\">mode<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">Platform<\/span>:<span class=\"w\">     <\/span><span class=\"nv\">BCM2835<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">Build<\/span><span class=\"w\"> <\/span><span class=\"nv\">time<\/span>:<span class=\"w\">   <\/span><span class=\"nv\">Mar<\/span><span class=\"w\"> <\/span><span class=\"mi\">17<\/span><span class=\"w\"> <\/span><span class=\"mi\">2016<\/span><span class=\"w\"> <\/span><span class=\"o\">-<\/span><span class=\"w\"> <\/span><span class=\"mi\">13<\/span>:<span class=\"mi\">11<\/span>:<span class=\"mi\">12<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">ch<\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"nv\">systime<\/span><\/span>\n<span class=\"code-line\"><span class=\"mi\">8434<\/span><\/span>\n<span class=\"code-line\"><span class=\"nv\">ch<\/span><span class=\"o\">&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Nun k&ouml;nnt ihr anfangen f&uuml;r das Echtzeitbetriebssystem Programme zu entwickeln. Daf&uuml;r m&uuml;sst ihr das Betriebssystem immer wieder neu bauen, aber das ist nicht sonderlich langwierig.<\/p>\n<p>[1] <a href=\"http:\/\/www.chibios.org\">http:\/\/www.chibios.org<\/a><br\/>\n[2] <a href=\"http:\/\/www.stevebate.net\/chibios-rpi\/GettingStarted.html\">http:\/\/www.stevebate.net\/chibios-rpi\/GettingStarted.html<br\/>\n<\/a>[3] <a href=\"https:\/\/launchpad.net\/gcc-arm-embedded\">https:\/\/launchpad.net\/gcc-arm-embedded<\/a><br\/>\n[4] <a href=\"https:\/\/www.adafruit.com\/products\/954\">https:\/\/www.adafruit.com\/products\/954<\/a><br\/>\n[5] <a href=\"https:\/\/learn.adafruit.com\/adafruits-raspberry-pi-lesson-5-using-a-console-cable\/connect-the-lead\">https:\/\/learn.adafruit.com\/adafruits-raspberry-pi-lesson-5-using-a-console-cable\/connect-the-lead<\/a><\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Raspberry Pi"}},{"@attributes":{"term":"Bare Metal"}},{"@attributes":{"term":"Realtime"}},{"@attributes":{"term":"Betriebssystem"}},{"@attributes":{"term":"Echtzeit"}}]},{"title":"Raspberry Pi Betriebssystem | Assembler","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/raspberry-pi-betriebssystem-assembler.html","rel":"alternate"}},"published":"2015-12-30T14:39:00+01:00","updated":"2015-12-30T14:39:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-12-30:\/informatik\/raspberry-pi-betriebssystem-assembler.html","summary":"<p>Hallo.<\/p>\n<p>Aktuell besch&auml;ftige ich mich mit dem Raspberry Pi und dem enthaltenen BCM2835-Chip, sowie mit ARM-Assembler. Dazu verfolge ich dieses Tutorial der Cambridge University <a href=\"http:\/\/www.cl.cam.ac.uk\/projects\/raspberrypi\/tutorials\/os\/\">[1]<\/a>. Das Tutorial f&uuml;hrt in das Thema Assembler ein, und zeigt einige interessante Wege den Pi einfache Sachen tun zu lassen. Angefangen davon eine GPIO-LED blinken \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>Aktuell besch&auml;ftige ich mich mit dem Raspberry Pi und dem enthaltenen BCM2835-Chip, sowie mit ARM-Assembler. Dazu verfolge ich dieses Tutorial der Cambridge University <a href=\"http:\/\/www.cl.cam.ac.uk\/projects\/raspberrypi\/tutorials\/os\/\">[1]<\/a>. Das Tutorial f&uuml;hrt in das Thema Assembler ein, und zeigt einige interessante Wege den Pi einfache Sachen tun zu lassen. Angefangen davon eine GPIO-LED blinken zu lassen, bis hin zur Benutzung von Maus und Tastatur sowie Bildschirm. Das Tutorial ist gut und anf&auml;ngerfreundlich geschrieben und l&auml;sst euch auch die M&ouml;glichkeit selbst zu probieren und selbst Code zu schreiben, und damit zu testen ob ihr die Theorie verstanden habt.<\/p>\n<p>Der gebaute Kern (siehe dazu unter Downloads das Makefile) wird auf eine SD-Karte vom Raspberry Pi kopiert, wo sich bereits ein Raspbian Kernel befunden hat. Dort wird kernel.img &uuml;berschrieben. Das f&uuml;hrt dazu, dass der enthaltene Bootloader euren Kernel anstelle den Linux-Kern bootet.<\/p>\n<p>Der Assembler-Code von ARM ist recht simpel (sind ja auch RISC-CPUs). Ein sehr gutes Nachschlagewerk daf&uuml;r ist <a href=\"http:\/\/www.heyrick.co.uk\/armwiki\/Main_Page\">[2]<\/a>.<\/p>\n<p>Ich kann jedem Informatiker empfehlen sich mit der Hardware und der Programmierung eines Raspberry Pis auf der Ebene auseinander zu setzen. Die Hardware ist hinreichend gut beschrieben <a href=\"https:\/\/www.raspberrypi.org\/documentation\/hardware\/raspberrypi\/bcm2835\/README.md\">[3]<\/a>. Mit dem Tutorial der Cambridge University ist ein erster Anfang geschaffen, den ihr weiter ausbauen k&ouml;nnt und ein komplettes Betriebssystem schreiben k&ouml;nnt. Nat&uuml;rlich k&ouml;nnt ihr auch sowohl Assembler als auch eine h&ouml;here Sprache, wie C benutzen.<\/p>\n<p>[1] <a href=\"http:\/\/www.cl.cam.ac.uk\/projects\/raspberrypi\/tutorials\/os\/\">http:\/\/www.cl.cam.ac.uk\/projects\/raspberrypi\/tutorials\/os\/<br\/>\n<\/a>[2] <a href=\"http:\/\/www.heyrick.co.uk\/armwiki\/Main_Page\">http:\/\/www.heyrick.co.uk\/armwiki\/Main_Page<\/a><br\/>\n[3] <a href=\"https:\/\/www.raspberrypi.org\/documentation\/hardware\/raspberrypi\/bcm2835\/README.md\">https:\/\/www.raspberrypi.org\/documentation\/hardware\/raspberrypi\/bcm2835\/README.md<\/a><\/p>\n<p>Folgendes Beispiel l&auml;sst ein SOS-Morsecode auf der ACT-LED blinken:<\/p>\n<p>main.s<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"p\">.<\/span><span class=\"n\">section<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">init<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">_start<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nl\">_start<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"cm\">\/* enabling the ACT-Pin *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_address<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">16<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_pinmode<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ loading the pattern into r3, mask into r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"n\">pattern<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r5<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mh\">0x80000000<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nl\">blinkloop<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"cm\">\/* sets or resets according to the current pattern-value *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">16<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">and<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_write<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mi\">250000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">delay_ms<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ror<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">b<\/span><span class=\"w\"> <\/span><span class=\"n\">blinkloop<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"p\">.<\/span><span class=\"n\">section<\/span><span class=\"w\"> <\/span><span class=\"p\">.<\/span><span class=\"n\">data<\/span><\/span>\n<span class=\"code-line\"><span class=\"c1\">\/\/ ldr works only if the data is set on an address multiple of 4<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">.<\/span><span class=\"n\">align<\/span><span class=\"w\"> <\/span><span class=\"mi\">2<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">pattern<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">.<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"mb\">0b10010010111001110011100100100100<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>gpio.s<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">wait<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_address<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_write<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_pinmode<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief waits for about r0 seconds<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param r0 amount of time the pi should wait (in seconds)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\return NONE<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">wait<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">beq<\/span><span class=\"w\"> <\/span><span class=\"n\">wait_back<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sub<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mh\">0x800000<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">innerloop<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sub<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"err\">#<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bne<\/span><span class=\"w\"> <\/span><span class=\"n\">innerloop<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">b<\/span><span class=\"w\"> <\/span><span class=\"n\">wait<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">wait_back<\/span><span class=\"p\">:<\/span><span class=\"w\">    <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"cm\">\/* jump back *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/********************\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/** GPIO - SECTION **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/********************\/<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief returns the GPIO-base address in r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\return r0 GPIO-base address<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">gpio_address<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mh\">0x20200000<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief writes a value to the GPIO-Pin (i.e. writes 1 to set or 1 to clear)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param r0 GPIO-Pin<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param r1 output-value (1 for on, 0 for off)<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">gpio_write<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">53<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">movhi<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/cmp r1, #1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/movhi pc, lr<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">push<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">lr<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_address<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r0 -&gt; GPIO-base address<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r1 -&gt; output value<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r2 -&gt; GPIO-Pin<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/! still r1 is referenced here<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">addhi<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">28<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">addls<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">40<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">31<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">subhi<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">32<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">addhi<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">4<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">lsl<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">str<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r0<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pop<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">pc<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief sets the PIN into the mode we want<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param r0 GPIO-Pin<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param r1 GPIO-Mode<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\return NONE<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">gpio_pinmode<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"cm\">\/** if (r0&gt;53 || r1&gt;7) return **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">53<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmpls<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">7<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">movhi<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">push<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">lr<\/span><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ save r0 (the pinnumber)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">gpio_address<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r0 =&gt; GPIO_address<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r1 =&gt; mode<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r2 =&gt; pin<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"nl\">pincalc<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">9<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">subhi<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">10<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">addhi<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">bhi<\/span><span class=\"w\"> <\/span><span class=\"n\">pincalc<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r0 =&gt; correct address for the pin<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r1 =&gt; mode (0-7)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r2 =&gt; pin-offset (0-9)<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ r2 = r2*3, because we need to shift r1 by r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">add<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lsl<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">lsl<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">push<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"n\">r6<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">7<\/span><span class=\"w\"> <\/span><span class=\"c1\">\/\/ 000...00111<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">lsl<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mvn<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"w\">    <\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ get the currently set GPIO-register-values <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"n\">r2<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ mask the according values to 0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">and<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ add the mode to the mode-vector<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">orr<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ store the mode-vector back to the GPIO-memory<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">str<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r0<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pop<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"n\">r6<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ return<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pop<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">pc<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>timer.s<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">delay_ms<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"p\">.<\/span><span class=\"n\">globl<\/span><span class=\"w\"> <\/span><span class=\"n\">delay<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief returns the base address of the timer<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">counteraddr<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mh\">0x20003000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief waits for the given amount of seconds<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param r0 amount of seconds <\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\note is maybe not that exact :\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">delay<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">push<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">r5<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ using ldr, not 'mov r0, #1000000' because immediate<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ is not big enough to hold decimal 1000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"mi\">1000000<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">delay_inner<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">0<\/span><span class=\"w\">    <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bls<\/span><span class=\"w\"> <\/span><span class=\"n\">delay_out<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">sub<\/span><span class=\"w\"> <\/span><span class=\"n\">r5<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">b<\/span><span class=\"w\"> <\/span><span class=\"n\">delay_ms<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">b<\/span><span class=\"w\"> <\/span><span class=\"n\">delay_inner<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nl\">delay_out<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pop<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">r5<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">pc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">lr<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cm\">\/**<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\brief waits for the given amount of microseconds<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> * \\param r0 amount of microseconds<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\"> **\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"nl\">delay_ms<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">push<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">lr<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">push<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"n\">r7<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mov<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r0<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bl<\/span><span class=\"w\"> <\/span><span class=\"n\">counteraddr<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">4<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">8<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">add<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r2<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r4<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">addcs<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">1<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nl\">delay_ms_inner<\/span><span class=\"p\">:<\/span><span class=\"w\">    <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">4<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ldr<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"p\">[<\/span><span class=\"n\">r0<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"err\">#<\/span><span class=\"mi\">8<\/span><span class=\"p\">]<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmp<\/span><span class=\"w\"> <\/span><span class=\"n\">r1<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r6<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">cmpls<\/span><span class=\"w\"> <\/span><span class=\"n\">r3<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">bhi<\/span><span class=\"w\"> <\/span><span class=\"n\">delay_ms_inner<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pop<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">r6<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">r7<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">pop<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><span class=\"n\">pc<\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Raspberry Pi"}},{"@attributes":{"term":"Betriebssystem"}},{"@attributes":{"term":"Bare Metal"}},{"@attributes":{"term":"BakingPi"}}]},{"title":"FLTK: Fast Light Toolkit","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/fltk-fast-light-toolkit.html","rel":"alternate"}},"published":"2015-12-19T13:47:00+01:00","updated":"2015-12-19T13:47:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-12-19:\/informatik\/fltk-fast-light-toolkit.html","summary":"<p>Hallo.<\/p>\n<p>Aktuell besch&auml;ftige ich mich mit dem FLTK, dem Fast Light Toolkit (v.1.3.3), welches eine Bibliothek ist, um GUI-Programmierung in C++ zu betreiben. Daf&uuml;r gibt es offenbar auch eine Python-Anbindung.<\/p>\n<p>Um ein einfaches Fenster zu erzeugen, mit einem Button, der beim Klicken die Farbe &auml;ndert ist folgender \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>Aktuell besch&auml;ftige ich mich mit dem FLTK, dem Fast Light Toolkit (v.1.3.3), welches eine Bibliothek ist, um GUI-Programmierung in C++ zu betreiben. Daf&uuml;r gibt es offenbar auch eine Python-Anbindung.<\/p>\n<p>Um ein einfaches Fenster zu erzeugen, mit einem Button, der beim Klicken die Farbe &auml;ndert ist folgender Code ganz n&uuml;tzlich:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;FL\/Fl.H&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;FL\/Fl_Window.H&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;FL\/Fl_Button.H&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;FL\/Fl_Widget.H&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">bool<\/span><span class=\"w\"> <\/span><span class=\"n\">state<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">btnpress<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">Fl_Widget<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">w<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">data<\/span><span class=\"w\"> <\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">state<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">w<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">labelcolor<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0x4cff0000<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">w<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">label<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"@circle\"<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">w<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">color<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xccff0000<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">w<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">color<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xffb74800<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">w<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">label<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"@+9circle\"<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">w<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">labelcolor<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xe7552c00<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">state<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">!<\/span><span class=\"n\">state<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">argc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">**<\/span><span class=\"n\">argv<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">Fl_Window<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">window<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"k\">new<\/span><span class=\"w\"> <\/span><span class=\"n\">Fl_Window<\/span><span class=\"p\">(<\/span><span class=\"mi\">100<\/span><span class=\"p\">,<\/span><span class=\"mi\">100<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">340<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"mi\">340<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Ehhhh! Hello W&ouml;rld<\/span><span class=\"se\">\\0<\/span><span class=\"s\">\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">Fl_Button<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">btn<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"k\">new<\/span><span class=\"w\"> <\/span><span class=\"n\">Fl_Button<\/span><span class=\"p\">(<\/span><span class=\"mi\">20<\/span><span class=\"p\">,<\/span><span class=\"mi\">40<\/span><span class=\"p\">,<\/span><span class=\"mi\">300<\/span><span class=\"p\">,<\/span><span class=\"mi\">100<\/span><span class=\"p\">,<\/span><span class=\"s\">\"\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">btn<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">box<\/span><span class=\"p\">(<\/span><span class=\"n\">FL_FLAT_BOX<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">btn<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">color<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xffb74800<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">btn<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">label<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"s\">\"@+9circle\"<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">btn<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">labelcolor<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"mh\">0xe7552c00<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">btn<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">align<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">FL_ALIGN_TEXT_NEXT_TO_IMAGE<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">btn<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">shortcut<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">FL_SHIFT<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\"> <\/span><span class=\"sc\">'b'<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">btn<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">callback<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">btnpress<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">window<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">end<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">window<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">show<\/span><span class=\"p\">(<\/span><span class=\"n\">argc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">argv<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"n\">Fl<\/span><span class=\"o\">::<\/span><span class=\"n\">run<\/span><span class=\"p\">();<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p><em>ptnpress<\/em> ist ein Callback, der die Farbe des Buttons &auml;ndert. <em>new<\/em> <em>Fl_Window()<\/em> erzeugt ein Fenster, mit der angegeben Position (x,y), Gr&ouml;&szlig;e (w,h) und Label, <em>new Fl_Button()<\/em> erzeugt den Button mit der Positon, Gr&ouml;&szlig;e und keinem Label.<\/p>\n<p><em>btn-&gt;box<\/em> legt die Verzierung des Buttons fest, <em>color<\/em> dessen Farbe, <em>label<\/em> dessen Labeltext. Wichtig ist hier, dass mit <em>@<\/em> ein Sonderzeichen escaped wird, dh. <em>\\@circle<\/em> erzeugt einen Kreis auf dem Button. <em>align<\/em> richtet den Labeltext aus (hier eigentlich unn&uuml;tz), <em>shortcut<\/em> erzeugt einen Tastaturshortcut (hier Shift + b) und <em>callback<\/em> registriert die Callbackfunktion mit dem Button. Der Callback wird gerufen, wenn sich der Wert &auml;ndert (dh. hier: wenn der Button gedr&uuml;ckt wird).<\/p>\n<p>Die Widgets werden automatisch zur letzten erstellten Gruppe hinzugef&uuml;gt (hier <em>window<\/em>), bis dessen <em>end()<\/em>-Methode gerufen wird. <em>windows-&gt;show<\/em> zeigt das Fenster an.<\/p>\n<p>Ich hoffe dieses kleine Beispiel hilft euch FLTK zu verstehen.<\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Beispiel"}},{"@attributes":{"term":"Button"}},{"@attributes":{"term":"FLTK"}},{"@attributes":{"term":"GUI"}},{"@attributes":{"term":"Hello World"}}]},{"title":"Raspberry Pi Model B+ und Gertboard","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/raspberry-pi-model-b-und-gertboard.html","rel":"alternate"}},"published":"2015-11-04T15:27:00+01:00","updated":"2015-11-04T15:27:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-11-04:\/informatik\/raspberry-pi-model-b-und-gertboard.html","summary":"<p>Aktuell arbeite ich an Raspberry Pi Model B+ zusammen mit dem Gertboard-Erweiterungsboard. Da der Aufbau f&uuml;r die Bildung verwendet werden soll, das hei&szlig;t, dass Studierende auf den Aufbau losgelassen werden soll, muss die Konstruktion maximal idiotensicher und nach M&ouml;glichkeit unkaputtbar gemacht werden.<\/p>\n<p>Um die Unterseite des Pi zu sch&uuml;tzen, haben \u2026<\/p>","content":"<p>Aktuell arbeite ich an Raspberry Pi Model B+ zusammen mit dem Gertboard-Erweiterungsboard. Da der Aufbau f&uuml;r die Bildung verwendet werden soll, das hei&szlig;t, dass Studierende auf den Aufbau losgelassen werden soll, muss die Konstruktion maximal idiotensicher und nach M&ouml;glichkeit unkaputtbar gemacht werden.<\/p>\n<p>Um die Unterseite des Pi zu sch&uuml;tzen, haben wir damit angefangen die Pis auf einen Kork-Untersetzer vom Ikea zu verschrauben. Das Gertboard kann mitsamt den mitgelieferten F&uuml;&szlig;en ebenfalls auf die Korkplatte geschraubt werden. Dazu wurden die Platten zun&auml;chst gebohrt, dann jeweils unter Schrauben eine Unterlegscheibe auf beiden Seiten (bis auf beim Pi, dort auf der Seite des Pi jeweils 5 Unterlegscheiben).<\/p>\n<p>Um den Pi weiter zu sch&uuml;tzen wurden dann Plastik-Unterlegscheiben auf den drei Unterlegscheiben-Stapel des Pi gelegt, und auch zwischen Pi und Mutter.<\/p>\n<p>Aber die Konstruktion passt nicht ganz auf den Kork-Unterlegscheibe, der Ethernetport schaut &uuml;ber. Das soll in unserem Anwendungsbereich aber nicht weiter st&ouml;ren. Daf&uuml;r ist auf der Korkscheibe gen&uuml;gend Platz f&uuml;r mehrere Etiketten, sodass dort bspw. Hostnames oder IP-Adressen aufgebracht werden k&ouml;nnen.<\/p>\n<p>So sollten die Pis und die Gertboards auch die unachtsamsten Studenten und Studentinnen &uuml;berleben.<\/p>\n<p><a href=\"\/data\/thumbnail\/pi02_full.jpg\"><img alt=\"Raspberry Pi mit Gertboard auf einem Korkuntersetzer\" src=\"\/data\/thumbnail\/pi02_large.jpg\" width=\"100%\"\/><\/a> <\/p>\n<p>Man beachte, dass der Pi nur mit drei Schrauben festgemacht wird, da das Loch (hier unten rechts) nicht mehr &uuml;ber dem Korkuntersetzer ist.<\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"DevOG: Internationalisierung","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/devog-internationalisierung.html","rel":"alternate"}},"published":"2015-11-01T00:59:00+01:00","updated":"2015-11-01T00:59:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-11-01:\/sonstiges\/devog-internationalisierung.html","summary":"<p>Ich arbeite seit einer Weile am Oettinger Games Code. Zum einen wartet seit einiger Zeit ein Internationalisierungssystem darauf scharf geschalten zu werden, zum anderen habe ich noch einige kleinere &Auml;nderungen am Game-Modul durchgef&uuml;hrt, die ich recht spannend finde.<\/p>\n<p>Das letzte zuerst: ich habe zu den Screenshots jetzt eine Eigenschaft \"system \u2026<\/p>","content":"<p>Ich arbeite seit einer Weile am Oettinger Games Code. Zum einen wartet seit einiger Zeit ein Internationalisierungssystem darauf scharf geschalten zu werden, zum anderen habe ich noch einige kleinere &Auml;nderungen am Game-Modul durchgef&uuml;hrt, die ich recht spannend finde.<\/p>\n<p>Das letzte zuerst: ich habe zu den Screenshots jetzt eine Eigenschaft \"system\" definiert, die angibt, von welchem System der Screenshot stammt. So wird es m&ouml;glich verschiedene Screenshot-Stapel zu haben, die jeweils nach System sortiert sind. Damit soll etwas mehr Ordnung geschaffen werden, sucht ein Nutzer bspw. konkret nach der PSP-Variante, so kann er den Stapel der PSP-Screenshots durchgehen. Au&szlig;erdem wird neben dem PSP-Reviewtext nun nurnoch der PSP-Screenshot-Stapel angezeigt.<\/p>\n<p>Au&szlig;erdem plane ich noch ein Modul zu implementieren, welches eine Serie von Spielen darstellen soll. So soll, jedenfalls ist es so geplant, auf der Detailseite zu einem Spiel, unten, eine Darstellung platziert werden, die anzeigt, welche Spiele in der Serie vor und welche nach dem aktuell gezeigten Spiel kamen. So kann der Nutzer bspw. den Verlauf einer Serie nachvollziehen. Au&szlig;erdem sieht er Spiele, die er vielleicht verpasst hat. Wichtig ist dabei die 1:n Beziehung, da ein Spiel in mehreren Serien erscheinen k&ouml;nnte, bspw. so genannte Cross-Over-Spiele.<\/p>\n<p>Nun zum Elefanten im Raum: die Lokalisierung. Unter Lokalisierung (l10n) oder Internationalisierung (i18n) versteht man das Anbieten einer Software in mehreren Sprachen. Dazu m&uuml;ssen oft bestimmte Vorkehrungen getroffen werden, zum Beispiel muss beachtet werden, dass teilweise andere Alphabete oder Schreibrichtungen verwendet werden. Soweit wurde das hier nicht implementiert. Von Oettinger Games werden nur links-nach-rechts-Schriften unterst&uuml;tzt.<\/p>\n<p>Geplant ist, die Seite komplett in Deutsch und Englisch anzubieten, ausgenommen davon w&auml;ren Reviewvideos, die ihrer Natur wegen nur einsprachig gehalten sein k&ouml;nnen und Achievement Guides, die - hoffentlich - generisch genug erstellt werden k&ouml;nnen, sodass sowohl deutsche als auch internationale Nutzerinnen und Nutzer sie verwenden k&ouml;nnen.<\/p>\n<p>Die Internationalisierung funktioniert hier so, dass es eine Standardsprache gibt (hier Deutsch), und alle anderen nur &Uuml;bersetzungen des deutschen Originals sind. Dh. ist keine &Uuml;bersetzung in der gew&uuml;nschten Sprache verf&uuml;gbar, so wird die deutsche Version angezeigt. Der Zugriff auf die Datenbank erfolgt nun zweistufig. Zun&auml;chst wird der deutsche Text inkl. Metadaten aus der Datenbank geholt, dann wird versucht einen &uuml;bersetzten Text in der gew&auml;hlten Sprache zu finden. Wird er gefunden, wird der deutsche Text mit dem &uuml;bersetzten Text ersetzt und angezeigt. Ist keine &Uuml;bersetzung verf&uuml;gbar, wird der deutsche Text im Speicher beibehalten und somit sp&auml;ter angezeigt.<\/p>\n<p>Der Ansatz ist generisch, sodass es f&uuml;r die Module kaum einen nennenswerten Unterschied gibt. Lediglich die localize Methode muss gerufen werden, um die Erkennung der gew&auml;hlten Sprache, und darum auch &Uuml;bersetzungen von versch. Modulen gegeneinander abzuschirmen k&uuml;mmert sich das Lokalisierungssystem. Statischer Text wird aus JSON-Dateien gelesen und zur Laufzeit durch Rufen der Methode \"text\" eingef&uuml;gt. Sollte keine Lokalisierungsdatei angegeben sein (in den Konfigurationen des Moduls) wird der Standardtext eingesetzt, der sonst als Hash verwendet wird.<\/p>\n<p>F&uuml;r mich ist das eigentlich eine recht spannende Technik, da es mir sehr darauf ankam, den vorhandenen Code m&ouml;glichst wenig ver&auml;ndern zu m&uuml;ssen. Ich denke, das ist mir sehr gut gelungen. Wenigstens muss ich die vorhandenen Tabellen nicht anr&uuml;hren, sondern konnte die Funktionalit&auml;t gut in die lang.php packen, und damit getrennt von den eigentlichen Moduln.<\/p>","category":{"@attributes":{"term":"Sonstiges"}}},{"title":"Projekt: Automatische Suche nach Preisen von Videospielen","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/projekt-automatische-suche-nach-preisen-von-videospielen.html","rel":"alternate"}},"published":"2015-08-03T23:40:00+02:00","updated":"2015-08-03T23:40:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-08-03:\/informatik\/projekt-automatische-suche-nach-preisen-von-videospielen.html","summary":"<p>Hallo.<\/p>\n<p>Dass ich Videospiele sammele, d&uuml;rfte kein Geheimnis sein, Hinweise darauf gibt es ja genug (<a href=\"http:\/\/www.oettingergames.de\">OettingerGames<\/a>). Nun passiert es mir recht h&auml;ufig, dass ich auf Ebay oder sonstigen Plattformen Videospiele entdecke oder Sammlungen entdecke, und mir denke - wie viel sind die Spiele eigentlich wert, dh. wie viel kann ich daf&uuml;r \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>Dass ich Videospiele sammele, d&uuml;rfte kein Geheimnis sein, Hinweise darauf gibt es ja genug (<a href=\"http:\/\/www.oettingergames.de\">OettingerGames<\/a>). Nun passiert es mir recht h&auml;ufig, dass ich auf Ebay oder sonstigen Plattformen Videospiele entdecke oder Sammlungen entdecke, und mir denke - wie viel sind die Spiele eigentlich wert, dh. wie viel kann ich daf&uuml;r bezahlen, und wie viel ist zu viel. Bislang habe ich mich an die Regel gehalten pro Spiel weniger als 2 &euro; zu bezahlen, das hat auch meistens ganz gut geklappt, bei solchen Spielen wie StarFox Assault funktioniert das aber nicht mehr.<\/p>\n<p>Daher w&auml;re es praktisch ein Programm zu haben, was automatisch mehrere Website abcheckt, am liebsten in zeitlichen Intervallen und die angebotenen Artikel + Preise in eine Datenbank aufnimmt. Sp&auml;ter* soll dann mithilfe der Daten ein Trend und ein Durchschnittspreis der letzten X (Tage|Wochen|Monate) errechnet werden k&ouml;nnen. Theoretisch w&auml;re es sogar m&ouml;glich diese Informationen auf Oettinger Games auszustellen, allerdings bed&uuml;rfte es dazu den Umzug auf einen vServer, den ich im Moment nicht durchf&uuml;hren kann und m&ouml;chte. Das Programm wird ein C-Programm, welches sich &uuml;ber bereitgestellte APIs Informationen &uuml;ber Preise zusammensammelt. Theoretisch w&auml;re es auch m&ouml;glich den aktuell g&uuml;nstigsten Preis f&uuml;r ein Spiel zu erfassen und einen Link anzeigen zu lassen, wo das Spiel gekauft werden kann.<\/p>\n<p>Das w&uuml;rde prinzipiell mit jedem Produkt funktionieren, dh. mit Filmen, B&uuml;chern, Waschmaschinen. Dieses Programm k&ouml;nnte das Leben von Resellern erleichtern, oder Kunden vor Fehlk&auml;ufen bewahren. Der n&auml;chste Schritt w&auml;re dann sogar eine MetaCritic-Bewertung anzuzeigen - direkt neben dem Preis. Ziel der Auswertung k&ouml;nnte es sein, Spiele mit m&ouml;glichst vielen Punkten f&uuml;r m&ouml;glichst wenig Geld zu bekommen, dh. m&ouml;glichst viele Punkte f&uuml;r m&ouml;glichst wenig Geld. So k&ouml;nnte ein Mittelwert gebildet werden, wie viel Geld pro MetaCritic-Punkt verlangt wird. Eine Stapelverarbeitung von Spielen muss nat&uuml;rlich ebenso m&ouml;glich sein.<\/p>\n<p>Vielleicht k&ouml;nnte ich demn&auml;chst(tm) eine erste Version des Programms fertig haben, das w&uuml;rde ich dann entsprechend hier irgendwo ver&ouml;ffentlichen.<\/p>\n<p>* Sp&auml;ter - das bezieht sich darauf, dass die Anwendung zyklisch Daten &uuml;ber 'abonnierte' Spiele bezieht, und eine andere Anwendung die Daten auswertet. Der erste Schritt w&auml;re eine Auswertung von Spielen zu einem gegebenen Zeitpunkt, ohne zyklisch Daten abzufragen.<\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"Amazon"}},{"@attributes":{"term":"Anwendung"}},{"@attributes":{"term":"Auswertung"}},{"@attributes":{"term":"Ebay"}},{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"MetaCritic"}},{"@attributes":{"term":"Oettinger Games"}},{"@attributes":{"term":"Preise"}},{"@attributes":{"term":"Programm"}},{"@attributes":{"term":"Videospiele"}}]},{"title":"Verl\u00e4sslichkeit auf Graphen","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/verlaesslichkeit-auf-graphen.html","rel":"alternate"}},"published":"2015-06-29T10:30:00+02:00","updated":"2015-06-29T10:30:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-06-29:\/informatik\/verlaesslichkeit-auf-graphen.html","summary":"<p>Wie im letzten Blogpost zu sehen ist (<a href=\"\/informatik\/tcp-aufzeichnung-testlauf.html\">[1]<\/a>), entstehen bei dem Netzwerksniffer Graphen. Beim eigentlichen Projekt soll es darum gehen diese Graphen auszuwerten und Verl&auml;sslichkeitsaussagen zu generieren. Dazu m&uuml;sste ich mich erstmal auf eine Art von Graph beschr&auml;nken.<\/p>\n<p><strong>Topologiegraph<\/strong> Zun&auml;chst ist es m&ouml;glich aus den Aufzeichnungen herauszulesen, welche Verbindungen wie \u2026<\/p>","content":"<p>Wie im letzten Blogpost zu sehen ist (<a href=\"\/informatik\/tcp-aufzeichnung-testlauf.html\">[1]<\/a>), entstehen bei dem Netzwerksniffer Graphen. Beim eigentlichen Projekt soll es darum gehen diese Graphen auszuwerten und Verl&auml;sslichkeitsaussagen zu generieren. Dazu m&uuml;sste ich mich erstmal auf eine Art von Graph beschr&auml;nken.<\/p>\n<p><strong>Topologiegraph<\/strong> Zun&auml;chst ist es m&ouml;glich aus den Aufzeichnungen herauszulesen, welche Verbindungen wie oft Offline waren. Das k&ouml;nnte bspw. passieren, wenn ein Netzwerkger&auml;t &uuml;berlastet ist oder wenn der Computer &uuml;berlastet ist. Es ist also m&ouml;glich aus der Information, dass PC A eine Nachricht versendet worden ist, aber am PC B nicht angekommen ist, anzunehmen, dass die Verbindung f&uuml;r den Moment down ist \/ war. Aus der Anzahl, wie viele Nachrichten nicht angekommen ist, kann eine Verl&auml;sslichkeit der Verbindung berechnet werden. Davon ausgehend kann berechnet werden, wie hoch die Wahrscheinlichkeit ist, dass ein Knoten komplett von den anderen getrennt ist. (siehe [2])<\/p>\n<p><strong>Antwortzeiten<\/strong> Die Zeit, die ein Server ben&ouml;tigt um eine Anfrage zu bearbeiten (hier die Zeit zwischen Erhalten der Anfrage und Versenden der Antwort) wird als Antwortzeit bezeichnet. Nehmen wir an, dass jede Anfrage beantwortet wird (nicht nur mit einem ACK), dann k&ouml;nnen wir aus der Differenz zwischen dem Empfangsereignis und dem Sendeereignis die Antwortzeit berechnen und entsprechend an die Kante zwischen A und B eintragen. Aus einem solchen Graphen k&ouml;nnte man versuchen Abh&auml;ngigkeiten zwischen den Services zu erkennen. Das funktioniert allerdings nur dann, wenn wir eine nur die aktuellsten Nachrichten auswerten, dh. die Auswertung sollte zyklisch in kurzen Abst&auml;nden passieren. Es ist m&ouml;glich, dass sp&auml;ter durch eine andere Anfrage ein Kreis komplettiert wird, das darf nat&uuml;rlich nicht mit reinspielen. Aus dem Graph kann man aber auch ablesen, wo bei einer Anfrage die meiste Zeit verloren geht. Nicht beachtet werden hier Netzwerk&uuml;bertragungszeiten, sondern lediglich Antwortzeiten \/ Rechenzeiten der Computer.<\/p>\n<p><strong>Abh&auml;ngigkeiten<\/strong> Aus den Nachrichten direkt k&ouml;nnten Abh&auml;ngigkeiten zwischen Services erkannt werden. Dh. wird eine Nachricht von A nach B versendet, nehmen wir an, dass eine Abh&auml;ngigkeit von A nach B herrscht. Dh. A ist von B abh&auml;ngig, oder anders ausgedr&uuml;ckt, wenn B down ist, kann auch A seine Aufgabe nicht mehr (oder nicht mehr vollst&auml;ndig) erf&uuml;llen. Dazu m&uuml;ssen wir annehmen, dass jede Nachricht, die versendet ist, f&uuml;r den eigentlichen Zweck des Systems unerl&auml;sslich ist. Aus den aufgezeichneten Daten, l&auml;sst sich nicht schlussfolgern, ob Nachrichten eventuell auch wegfallen k&ouml;nnten, ohne dabei zu riskieren, dass das System ausfallen k&ouml;nnte. Aus Abh&auml;ngigkeiten k&ouml;nnten, wie oben beschrieben, Fault-Trees erstellt werden. Es bleibt zu &uuml;berlegen, was passiert, wenn Kreise entstehen.<\/p>\n<p>Das sind nur die M&ouml;glichkeiten, die mir eingefallen sind, bzw. durch die Lekt&uuml;re von [2] in den Kopf gekommen sind. Es geht bei dem Projekt nicht darum, Basisnachrichten zu ver&auml;ndern. W&auml;re es bspw. M&ouml;glich einen X-Trace-Header [3] in die Nachrichten beim Versenden einzubauen (versehen mit einer im gesamten System eindeutigen ID), k&ouml;nnte man den Weg dieser Nachricht beobachten und daraus Schlussfolgerungen &uuml;ber das Verhalten des Systems ziehen. Das ist in diesem Projekt aber nicht m&ouml;glich.<\/p>\n<p>[1] https:\/\/www.stefannaumann.de\/informatik\/tcp-aufzeichnung-testlauf.html\n[2] \"A Recursive Algorithm for Directed-Graph Reliability\" von J.A. Buzacott\n[3] \"X-Trace: A Persvasive Network Tracing Framework\" von R. Fonseca, G. Porter, R.H. Katz, S.Shenker und I.Stoica.<\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"TCP Aufzeichnung - Testlauf","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/tcp-aufzeichnung-testlauf.html","rel":"alternate"}},"published":"2015-06-24T11:47:00+02:00","updated":"2015-06-24T11:47:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-06-24:\/informatik\/tcp-aufzeichnung-testlauf.html","summary":"<p>Derzeit besch&auml;ftige ich mich damit einen Netzwerksniffer zu schreiben, der Informationen &uuml;ber alle gesendeten und empfangenen Nachrichten in einer MySQL Datenbank speichert. Aus den gespeicherten Informationen wird dann ein Multigraph erstellt, der zwischen jedem Knotenpaar mit Kanten Kommunikation &uuml;ber einen Port darstellt. Dazu gemessen werden soll die L&auml;nge der Verarbeitung \u2026<\/p>","content":"<p>Derzeit besch&auml;ftige ich mich damit einen Netzwerksniffer zu schreiben, der Informationen &uuml;ber alle gesendeten und empfangenen Nachrichten in einer MySQL Datenbank speichert. Aus den gespeicherten Informationen wird dann ein Multigraph erstellt, der zwischen jedem Knotenpaar mit Kanten Kommunikation &uuml;ber einen Port darstellt. Dazu gemessen werden soll die L&auml;nge der Verarbeitung der Nachricht, was bei der Verarbeitung gemacht werden kann, indem die n&auml;chste Nachricht gesucht wird, die vom Empf&auml;nger gesendet wird. Im Graph wird die Anfrage eingetragen (also in der Richtung vom Fragenden zum Server).<\/p>\n<p>Mein Testnetzerk besteht aus vier virtuellen Debian-Installationen; auf dem ersten ein Apache-Webserver, der ein PHP-Skript abspulen soll, was wiederum auf einem MySQL-Server (auf dem zweiten Knoten), einen FTP-Server (auf dem dritten) und wiederum auf einen Webserver (auf dem vierten) zugreifen soll. Das PHP-Skript des vierten Rechners greift dabei wiederum auf den MySQL-Server zu. So erh&auml;lt man einen recht einfachen Graphen mit f&uuml;nf Knoten (vier Rechnern und einem \"outside\", also au&szlig;erhalb des verteilten Systems) und 5 Kanten.<\/p>\n<p>Der Agent wird auf jedem Knoten eingerichtet und schn&uuml;ffelt ab dem Programmstart alle Nachrichten mit, die am Netzwerkger&auml;t ankommen oder abgesendet werden. Im Testlauf wurden alle Nachrichten auf einem MySQL-Server au&szlig;erhalb des Systems gespeichert und Nachrichten, die dorthin gehen bzw. von dort kamen direkt durch die pcap-Filter ausgefiltert. Auf dem konkreten System entsteht damit der unten stehende Graph. Auff&auml;llig sind dabei die Kanten in R&uuml;ckrichtung, die eigentlich nicht da sein d&uuml;rften, und daran die Ports im f&uuml;nfstelligen Bereich. Wo kommen die her?<\/p>\n<p><a href=\"\/data\/thumbnail\/topologie_full.jpg\"><img alt=\"topologie\" class=\"alignnone\" src=\"\/data\/thumbnail\/topologie_full.jpg\" width=\"100%\"\/><\/a><\/p>\n<p>Eine m&ouml;gliche Begr&uuml;ndung k&ouml;nnte sein, dass eine Bibliothek, die ich verwende zus&auml;tzliche Nachrichten versendet. Aber welche Bibliothek sollte das warum tun? Das sieht im ersten Moment aus, als w&uuml;rden die Agenten Peer 2 Peer miteinander kommunizieren. Aber wiederum nicht alle mit allen. Eine andere M&ouml;glichkeit ist, dass diese Nachrichten TCP-Nachrichten sind, die die Verbindung steuern. Erinnern wir uns, dass die Agenten nur Nachrichten aufzeichnen, und Informationen &uuml;ber TCP-Verbindungen v&ouml;llig verloren gehen. Dh. wir zeichnen auch Nachrichten auf, die f&uuml;r den Auf- und Abbau der TCP-Verbindung verantwortlich sind oder die eine Best&auml;tigung des Erhalts sind (ACK). Da ist es nat&uuml;rlich klar, dass diese Nachrichten genau in Gegenrichtung entstehen, werden doch Antworten des Server quittert.<\/p>\n<p>Eine Ver&auml;nderung des pcap-Filter, sodass keine TCP-Kontrollnachrichten mehr aufgesammelt werden, k&ouml;nnte also Abhilfe bringen. Dahingehend muss ich allerdings noch einmal nachlesen, inwiefern diese Kontrollinformationen an Nachrichten mit Payload gesetzt sein k&ouml;nnen, oder ob SYN, FIN, ACK,... immer an leeren Nachrichten verwendet werden.<\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"Apache Kafka vs. MySQL","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/apache-kafka-vs-mysql.html","rel":"alternate"}},"published":"2015-05-21T23:30:00+02:00","updated":"2015-05-21T23:30:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-05-21:\/informatik\/apache-kafka-vs-mysql.html","summary":"<p>Im Moment arbeite ich an der Anbindung des Sniffers, welchen ich fr&uuml;her kurz beschrieben habe, an eine MySQL-Datenbank um die aufgezeichneten Nachrichten eine Weile lang (hier f&uuml;r immer) speichern zu k&ouml;nnen. Ziel dessen soll es sein die Nachrichten im Anschluss zu verarbeiten, wenn der \/ die Sniffer eine Weile lang gelaufen \u2026<\/p>","content":"<p>Im Moment arbeite ich an der Anbindung des Sniffers, welchen ich fr&uuml;her kurz beschrieben habe, an eine MySQL-Datenbank um die aufgezeichneten Nachrichten eine Weile lang (hier f&uuml;r immer) speichern zu k&ouml;nnen. Ziel dessen soll es sein die Nachrichten im Anschluss zu verarbeiten, wenn der \/ die Sniffer eine Weile lang gelaufen sind.<\/p>\n<p>Zun&auml;chst war die Idee einen zentralen Nachrichtenbroker namens Kafka zu verwenden (siehe [1]). An diesen Server, der im Netzwerk gespiegelt oder mehrfach auftreten kann, werden Nachrichten geschickt, die sp&auml;ter wieder ausgelesen werden k&ouml;nnen. Kafka vergisst nach einer gewissen Zeit alte Nachrichten (was nicht immer schlecht sein muss, vor allem dann, wenn es eigentlich darum geht, auf halbwegs aktuellen Informationen weiterzuarbeiten). F&uuml;r mich st&ouml;rend sind allerdings einige Sachen am Kafka: Zum einen st&ouml;rt mich, dass Kafka und das offenbar darunter liegende Zookeeper auf der Java-VM laufen. Ich kann einfach nicht glauben, dass das schnell genug arbeiten k&ouml;nnen soll um viele Clienten abhandeln zu k&ouml;nnen. Au&szlig;erdem ist dezent st&ouml;rend, dass Kafka keine Anfragensprache wie SQL kann. F&uuml;r meine Auswertung wird es notwendig im Kontext einer gefundenen Nachricht bspw. die Antwort auf die Nachricht zu finden, was intuitiv mit MySQL durch die SQL-Abfragensprache einfacher zu realisieren ist. Allerdings f&auml;llt mir beim Schreiben des Textes auf, dass Kafka dazu sehr wohl in der Lage w&auml;re, und zwar durch den Offset - so kann man Kafka anweisen an einer bestimmten \"Stelle\" die Nachricht zu liefern. Diese Stelle ist f&uuml;r den Konsumenten beliebig, und kann im Programm ver&auml;ndert werden. So k&ouml;nnte man solange lesen, bis schlie&szlig;lich ein Filterkriterium nicht mehr stimmt (bspw. Timestamp).<\/p>\n<p>Die eigentliche Idee, warum MySQL also zum Einsatz kommen soll, ist, dass es eine Abfragensprache (SQL) unterst&uuml;tzt, mit deren Hilfe ich mir einfache Abfragen erhoffe und damit ein einfaches Gewinnen an Informationen ohne selbst unn&ouml;tig viele Daten wegwerfen zu m&uuml;ssen bzw. selbst aussortieren zu m&uuml;ssen, was, wie ich denke, Einfluss auf den Verarbeitungsprozess der Daten haben k&ouml;nnte.<\/p>\n<p>F&uuml;r die Anbindung von MySQL verwende ich den MySQL++-Wrapper (siehe [2]). Dieser objektorientierte Wrapper hat die Eigenschaft etwa so einfach zu bedienen zu sein, als h&auml;tte ich das entwickelt - ich neige dazu Funktionalit&auml;t zu wrappen und hinter recht einfachen Schnittstellen zu verstecken. Das einzige, was ihr tun m&uuml;sst, ist eine Verbindung herstellen und schon k&ouml;nnt ihr eine Abfrage an den MySQL Server stellen, was dieser auch sofort mit den Tupeln, die auf die Abfrage zutreffen, beantwortet: aus [3]<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"cmdline.h\"<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">\"printdata.h\"<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;mysql++.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;iostream&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;iomanip&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">using<\/span><span class=\"w\"> <\/span><span class=\"k\">namespace<\/span><span class=\"w\"> <\/span><span class=\"nn\">std<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><\/span>\n<span class=\"code-line\"><span class=\"nf\">main<\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">argc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">argv<\/span><span class=\"p\">[])<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ Get database access parameters from command line<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mysqlpp<\/span><span class=\"o\">::<\/span><span class=\"n\">examples<\/span><span class=\"o\">::<\/span><span class=\"n\">CommandLine<\/span><span class=\"w\"> <\/span><span class=\"n\">cmdline<\/span><span class=\"p\">(<\/span><span class=\"n\">argc<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">argv<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"n\">cmdline<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ Connect to the sample database.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">mysqlpp<\/span><span class=\"o\">::<\/span><span class=\"n\">Connection<\/span><span class=\"w\"> <\/span><span class=\"n\">conn<\/span><span class=\"p\">(<\/span><span class=\"nb\">false<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">conn<\/span><span class=\"p\">.<\/span><span class=\"n\">connect<\/span><span class=\"p\">(<\/span><span class=\"n\">mysqlpp<\/span><span class=\"o\">::<\/span><span class=\"n\">examples<\/span><span class=\"o\">::<\/span><span class=\"n\">db_name<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">cmdline<\/span><span class=\"p\">.<\/span><span class=\"n\">server<\/span><span class=\"p\">(),<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">cmdline<\/span><span class=\"p\">.<\/span><span class=\"n\">user<\/span><span class=\"p\">(),<\/span><span class=\"w\"> <\/span><span class=\"n\">cmdline<\/span><span class=\"p\">.<\/span><span class=\"n\">pass<\/span><span class=\"p\">()))<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ Retrieve a subset of the sample stock table set up by resetdb<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"c1\">\/\/ and display it.<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">mysqlpp<\/span><span class=\"o\">::<\/span><span class=\"n\">Query<\/span><span class=\"w\"> <\/span><span class=\"n\">query<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">conn<\/span><span class=\"p\">.<\/span><span class=\"n\">query<\/span><span class=\"p\">(<\/span><span class=\"s\">\"select item from stock\"<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">mysqlpp<\/span><span class=\"o\">::<\/span><span class=\"n\">StoreQueryResult<\/span><span class=\"w\"> <\/span><span class=\"n\">res<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">query<\/span><span class=\"p\">.<\/span><span class=\"n\">store<\/span><span class=\"p\">())<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"We have:\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">mysqlpp<\/span><span class=\"o\">::<\/span><span class=\"n\">StoreQueryResult<\/span><span class=\"o\">::<\/span><span class=\"n\">const_iterator<\/span><span class=\"w\"> <\/span><span class=\"n\">it<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">it<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">res<\/span><span class=\"p\">.<\/span><span class=\"n\">begin<\/span><span class=\"p\">();<\/span><span class=\"w\"> <\/span><span class=\"n\">it<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"n\">res<\/span><span class=\"p\">.<\/span><span class=\"n\">end<\/span><span class=\"p\">();<\/span><span class=\"w\"> <\/span><span class=\"o\">++<\/span><span class=\"n\">it<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"n\">mysqlpp<\/span><span class=\"o\">::<\/span><span class=\"n\">Row<\/span><span class=\"w\"> <\/span><span class=\"n\">row<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">it<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"sc\">'\\t'<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">row<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Failed to get item list: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">query<\/span><span class=\"p\">.<\/span><span class=\"n\">error<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"DB connection failed: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">conn<\/span><span class=\"p\">.<\/span><span class=\"n\">error<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">return<\/span><span class=\"w\"> <\/span><span class=\"mi\">1<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Das Programm wird gebaut mit:<\/p>\n<blockquote>\n<p>g++ main.cpp -lmysql++<\/p>\n<\/blockquote>\n<p>Leider hat mysql++ noch einige Macken, vor allem, dass die Bibliothek beim Bauen die installierte MySQL-Client-Bibliothek nicht finden konnte, weshalb ich mehrere Symlinks im \/usr\/-Ordner anlegen musste, bis das Bauen und Linken den Bibliothek endlich funktioniert hat. Au&szlig;erdem gibt es einen Fehler, dass irgendwo in er mysql++.h eine \"mysql_version.h\" inkludiert wird, die aber (jedenfalls bei mir) in \"mysql\/mysql_version.h\" liegt. Vielleicht ist das ein Fehler, exklusiv zu LinuxMint, aber nervig ist das allemal.<\/p>\n<p>Kafka auf der anderen Seite ist mit librdkafka++ [4] etwas schwieriger in der Handhabung. Einerseits verlangt die Bibliothek, dass ihr deutlich mehr macht als Verbindung aufbauen, es gibt Offsets und Partitionen zu setzen, ihr m&uuml;sst Server kennen und Ports, dazu noch das Thema, auf das ihr posten wollt. Das ist schon etwas komplexer, erlaubt daf&uuml;r aber auch die Daten semantisch zu ordnen, &auml;hnlich wie in MySQL die Datenbanken. Vorteil von Kafka ist, dass ihr die Daten zur Not auf Byteweise reinlegen k&ouml;nnt, wohingegen ihr bei MySQL darauf angewiesen seid, dass die Datentypen von MySQL die gleichen wie in eurem C-Programm sind.<\/p>\n<p>Daf&uuml;r ist das Bauen von librdkafka++ recht einfach, allerdings fordert das Bauen von euren Anwendungen mehrere Bibliotheken. So wird ein einfaches Programm gebaut [5] (aus den Beispielen der Bibliothek):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;iostream&gt;<\/span><\/code><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;string&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;cstdlib&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;cstdio&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;csignal&gt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;cstring&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"cp\">#include<\/span><span class=\"w\"> <\/span><span class=\"cpf\">&lt;librdkafka\/rdkafkacpp.h&gt;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"kt\">bool<\/span><span class=\"w\"> <\/span><span class=\"n\">run<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">static<\/span><span class=\"w\"> <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"nf\">sigterm<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"n\">sig<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"n\">run<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">false<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">class<\/span><span class=\"w\"> <\/span><span class=\"nc\">ExampleDeliveryReportCb<\/span><span class=\"w\"> <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"k\">public<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">DeliveryReportCb<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"k\">public<\/span><span class=\"o\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">dr_cb<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Message<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">message<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Message delivery for (\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"n\">len<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\" bytes): \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">message<\/span><span class=\"p\">.<\/span><span class=\"n\">errstr<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"k\">class<\/span><span class=\"w\"> <\/span><span class=\"nc\">ExampleEventCb<\/span><span class=\"w\"> <\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"k\">public<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">EventCb<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\"> <\/span><span class=\"k\">public<\/span><span class=\"o\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"kt\">void<\/span><span class=\"w\"> <\/span><span class=\"n\">event_cb<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Event<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">event<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">switch<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"p\">())<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"k\">case<\/span><span class=\"w\"> <\/span><span class=\"no\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"no\">Event<\/span><span class=\"o\">::<\/span><span class=\"no\">EVENT_ERROR<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"ERROR (\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">err2str<\/span><span class=\"p\">(<\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">err<\/span><span class=\"p\">())<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"): \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">str<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">err<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">==<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">ERR__ALL_BROKERS_DOWN<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span><span class=\"n\">run<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">false<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">break<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"k\">case<\/span><span class=\"w\"> <\/span><span class=\"no\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"no\">Event<\/span><span class=\"o\">::<\/span><span class=\"no\">EVENT_STATS<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"<\/span><span class=\"se\">\\\"<\/span><span class=\"s\">STATS<\/span><span class=\"se\">\\\"<\/span><span class=\"s\">: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">str<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">break<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"k\">case<\/span><span class=\"w\"> <\/span><span class=\"no\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"no\">Event<\/span><span class=\"o\">::<\/span><span class=\"no\">EVENT_LOG<\/span><span class=\"p\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">fprintf<\/span><span class=\"p\">(<\/span><span class=\"n\">stderr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"s\">\"LOG-%i-%s: %s<\/span><span class=\"se\">\\n<\/span><span class=\"s\">\"<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">severity<\/span><span class=\"p\">(),<\/span><span class=\"w\"> <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">fac<\/span><span class=\"p\">().<\/span><span class=\"n\">c_str<\/span><span class=\"p\">(),<\/span><span class=\"w\"> <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">str<\/span><span class=\"p\">().<\/span><span class=\"n\">c_str<\/span><span class=\"p\">());<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">break<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"k\">default<\/span><span class=\"o\">:<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"EVENT \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">type<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"s\">\" (\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">err2str<\/span><span class=\"p\">(<\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">err<\/span><span class=\"p\">())<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"): \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">event<\/span><span class=\"p\">.<\/span><span class=\"n\">str<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">break<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">  <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">};<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"kt\">int<\/span><span class=\"w\"> <\/span><span class=\"nf\">main<\/span><span class=\"w\"> <\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">string<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">string<\/span><span class=\"w\"> <\/span><span class=\"n\">topic_str<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"test3\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">string<\/span><span class=\"w\"> <\/span><span class=\"n\">host<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"s\">\"localhost:9092\"<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int32_t<\/span><span class=\"w\"> <\/span><span class=\"n\">partition<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Topic<\/span><span class=\"o\">::<\/span><span class=\"n\">PARTITION_UA<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"kt\">int64_t<\/span><span class=\"w\"> <\/span><span class=\"n\">start_offset<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Topic<\/span><span class=\"o\">::<\/span><span class=\"n\">OFFSET_BEGINNING<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ create configurations (global and topic)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Conf<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">conf<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Conf<\/span><span class=\"o\">::<\/span><span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Conf<\/span><span class=\"o\">::<\/span><span class=\"n\">CONF_GLOBAL<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Conf<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">tconf<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Conf<\/span><span class=\"o\">::<\/span><span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Conf<\/span><span class=\"o\">::<\/span><span class=\"n\">CONF_TOPIC<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ list of brokers<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">conf<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"metadata.broker.list\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">host<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ event callback<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ExampleEventCb<\/span><span class=\"w\"> <\/span><span class=\"n\">ex_event_cb<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">conf<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"event_cb\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">ex_event_cb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">signal<\/span><span class=\"p\">(<\/span><span class=\"n\">SIGINT<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">sigterm<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">signal<\/span><span class=\"p\">(<\/span><span class=\"n\">SIGTERM<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">sigterm<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ delivery callback<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">ExampleDeliveryReportCb<\/span><span class=\"w\"> <\/span><span class=\"n\">ex_dr_cb<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">conf<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"dr_cb\"<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"o\">&amp;<\/span><span class=\"n\">ex_dr_cb<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ create producer<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Producer<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">producer<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Producer<\/span><span class=\"o\">::<\/span><span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"n\">conf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"n\">producer<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Failed to create producer: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"n\">exit<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cout<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"% Created producer \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">producer<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">name<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"c1\">\/\/ create topic-handle<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Topic<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">topic<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Topic<\/span><span class=\"o\">::<\/span><span class=\"n\">create<\/span><span class=\"p\">(<\/span><span class=\"n\">producer<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">topic_str<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">tconf<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"n\">topic<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Failed to create topic: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">errstr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"n\">exit<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">for<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">string<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"p\">;<\/span><span class=\"w\"> <\/span><span class=\"n\">run<\/span><span class=\"w\"> <\/span><span class=\"k\">and<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">getline<\/span><span class=\"p\">(<\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cin<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"p\">);)<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">line<\/span><span class=\"p\">.<\/span><span class=\"n\">empty<\/span><span class=\"p\">())<\/span><span class=\"w\"> <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"n\">producer<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">poll<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">            <\/span><span class=\"k\">continue<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">      <\/span><span class=\"cm\">\/*<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">       * Produce message<\/span><\/span>\n<span class=\"code-line\"><span class=\"cm\">       *\/<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">ErrorCode<\/span><span class=\"w\"> <\/span><span class=\"n\">resp<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"n\">producer<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">produce<\/span><span class=\"p\">(<\/span><span class=\"n\">topic<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">partition<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">Producer<\/span><span class=\"o\">::<\/span><span class=\"n\">RK_MSG_COPY<\/span><span class=\"w\"> <\/span><span class=\"cm\">\/* Copy payload *\/<\/span><span class=\"p\">,<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">                                                    <\/span><span class=\"k\">const_cast<\/span><span class=\"o\">&lt;<\/span><span class=\"kt\">char<\/span><span class=\"w\"> <\/span><span class=\"o\">*&gt;<\/span><span class=\"p\">(<\/span><span class=\"n\">line<\/span><span class=\"p\">.<\/span><span class=\"n\">c_str<\/span><span class=\"p\">()),<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"p\">.<\/span><span class=\"n\">size<\/span><span class=\"p\">(),<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"nb\">NULL<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">resp<\/span><span class=\"w\"> <\/span><span class=\"o\">!=<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">ERR_NO_ERROR<\/span><span class=\"p\">)<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"% Produce failed: \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">err2str<\/span><span class=\"p\">(<\/span><span class=\"n\">resp<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"k\">else<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">          <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"% Produced message (\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">line<\/span><span class=\"p\">.<\/span><span class=\"n\">size<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\" bytes)\"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">producer<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">poll<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">run<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nb\">true<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">while<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"n\">run<\/span><span class=\"w\"> <\/span><span class=\"k\">and<\/span><span class=\"w\"> <\/span><span class=\"n\">producer<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">outq_len<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&gt;<\/span><span class=\"w\"> <\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span><span class=\"w\"> <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">{<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">cerr<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"s\">\"Waiting for \"<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">producer<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">outq_len<\/span><span class=\"p\">()<\/span><span class=\"w\"> <\/span><span class=\"o\">&lt;&lt;<\/span><span class=\"w\"> <\/span><span class=\"n\">std<\/span><span class=\"o\">::<\/span><span class=\"n\">endl<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">        <\/span><span class=\"n\">producer<\/span><span class=\"o\">-&gt;<\/span><span class=\"n\">poll<\/span><span class=\"p\">(<\/span><span class=\"mi\">1000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">delete<\/span><span class=\"w\"> <\/span><span class=\"n\">topic<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"k\">delete<\/span><span class=\"w\"> <\/span><span class=\"n\">producer<\/span><span class=\"p\">;<\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"n\">RdKafka<\/span><span class=\"o\">::<\/span><span class=\"n\">wait_destroyed<\/span><span class=\"p\">(<\/span><span class=\"mi\">5000<\/span><span class=\"p\">);<\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">}<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Gebaut wird mit:<\/p>\n<blockquote>\n<p>g++ main.cpp -g -lrdkafka++ -lrdkafka -lpthread -lz -lrt<\/p>\n<\/blockquote>\n<p>So. Abschlie&szlig;en bleibt die Frage offen, was genau ich nun verwenden will. Einerseits gef&auml;llt mir die einfachen Abfragen via MySQL, andererseits sehe ich auch die Vorteile von Kafka und halte den Nachrichtenserver f&uuml;r besser skalierend (vor allem, da sich die verschiedenen Nachrichtenbroker die Partitionen unter sich aufteilen). F&uuml;r die eigentliche Verarbeitung der Daten macht das kaum einen Unterschied. Bei MySQL muss ich hoffen, dass die Datentypen stimmen, die ich eingestellt habe, bei Kafka muss ich hoffen, dass er mir die Daten Byte-Weise so zur&uuml;ckliefert, wie er sie bekommt, auch wenn es sich nicht um druckbare Zeichen handelt.<\/p>\n<p>[1] http:\/\/www.kafka.apache.org<br\/>\n[2] http:\/\/www.tangentsoft.net\/mysql++\/<br\/>\n[3] http:\/\/www.tangentsoft.net\/mysql++\/doc\/html\/userman\/tutorial.html#simple<br\/>\n[4] https:\/\/github.com\/edenhill\/librdkafka<br\/>\n[5] https:\/\/www.proggen.org\/doku.php?id=user:naums:rdkafka_producer<\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"Linux: Beim Netzwerksniffing Programmnamen mitschneiden","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/linux-beim-netzwerksniffing-programmnamen-mitschneiden.html","rel":"alternate"}},"published":"2015-05-01T12:25:00+02:00","updated":"2015-05-01T12:25:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-05-01:\/informatik\/linux-beim-netzwerksniffing-programmnamen-mitschneiden.html","summary":"<p>Es gibt einige Netzwerksniffer bzw. Programme, die aufzeichnen, welche Daten gerade &uuml;ber ein Netzwerkinterface gesendet oder empfangen werden. Als bekanntestes Beispiel sei da wohl WireShark zu nennen. Die dabei benutze Programmbibliothek (pcap) kann aber auch einzeln in eigenen Programmen verwendet werden. Damit besch&auml;ftige ich mich im Moment.<\/p>\n<p>Zum Einen soll \u2026<\/p>","content":"<p>Es gibt einige Netzwerksniffer bzw. Programme, die aufzeichnen, welche Daten gerade &uuml;ber ein Netzwerkinterface gesendet oder empfangen werden. Als bekanntestes Beispiel sei da wohl WireShark zu nennen. Die dabei benutze Programmbibliothek (pcap) kann aber auch einzeln in eigenen Programmen verwendet werden. Damit besch&auml;ftige ich mich im Moment.<\/p>\n<p>Zum Einen soll es die Aufgabe sein, ein m&ouml;glichst vollst&auml;ndiges Bild des Netzwerks aus den mitgezeichneten Traces zu erhalten, zum anderen, soll aber auch erkannt werden, welche Anwendung an welchem Port lauscht. Diese Information kann f&uuml;r eine sp&auml;tere Auswertung der Daten n&uuml;tzlich sein. Bspw. k&ouml;nnte so erkannt werden, ob ein Server mit unsinnigen Nachrichten bombardiert wird, o.&Auml;.<\/p>\n<p>In erster N&auml;herung ist es mit pcap m&ouml;glich Nachrichten aufzusammeln, die vom Netzwerkger&auml;t kommen. Dann m&uuml;ssen wir noch den Port herausfinden. Die Funktion, die die Nachrichten verarbeiten kann, sieht etwa so aus:<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kt\">void<\/span><span class=\"w\">&nbsp;<\/span><span class=\"nf\">_recv_msg_cb<\/span><span class=\"w\"> <\/span><span class=\"p\">(<\/span><span class=\"w\"> <\/span><span class=\"n\">u_char<\/span><span class=\"o\">*<\/span><span class=\"w\"> <\/span><span class=\"n\">usr<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"k\">struct<\/span><span class=\"w\"> <\/span><span class=\"nc\">pcap_pkthdr<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">h<\/span><span class=\"p\">,<\/span><span class=\"w\"> <\/span><span class=\"k\">const<\/span><span class=\"w\"> <\/span><span class=\"n\">u_char<\/span><span class=\"w\"> <\/span><span class=\"o\">*<\/span><span class=\"n\">packet<\/span><span class=\"w\"> <\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Die Funktion erh&auml;lt unsigned char Daten vom Nutzer, eine Datenstruktur pcap_pkthdr, die die L&auml;nge der Nachricht sowie einen Timestamp enth&auml;lt und das Paket (als unsigned char) selbst. Nun kann man Byteweise aus dem Paket Daten auslesen, also bspw. IP-Adressen und Ports. Dazu muss aber auch beachtet werden, ob das Paket vom Rechner selbst versendet wurde, oder empfangen wurde.<\/p>\n<p>Zur Vereinfachung werden hier nur TCP-Pakete (bei Ethernet und IPv4) betrachtet. Wir wissen, dass ein Paket aus mehreren Layers besteht, die die eigentliche Payload (das was am Ende von der Anwendung verarbeitet wird, bzw. eigentlich versandt wurde) wie eine Art Zwiebelschale einh&uuml;llen. Unter [1] ist die Struktur des Ethernet Frames dargestellt. Zu Erkennen ist, dass das Payload (IP-Paket), bei 22 oder 26 Bytes Offset beginnt*. Unter [2] ist das IP-Paket dargestellt, was uns hier auch erstmal wenig interessiert. Es ist aber wichtig, dass dessen Payload (TCP-Paket) wiederum bei 24 Byte Offset beginnt. [3] beschreibt den Aufbau des TCP-Pakets. Source Port sind die ersten 16 Bit, Destination Port die n&auml;chsten 16 Bit. Dh. wollen wir die Ports abgreifen nehmen wir einen Versatz von 0 Byte bzgl. des Beginns des TCP-Pakets, bzw. von 2 Byte.<\/p>\n<p>Nun sollten wir den Port abgegriffen haben, was nun folgt ist das Herausfinden, welche Anwendung diesen Port benutzt - das muss nat&uuml;rlich zu der Zeit passieren, wenn das Paket abgegriffen wird. Dazu kann in erster N&auml;herung das Programm <em>lsof<\/em>&nbsp;verwendet werden. So besteht die M&ouml;glichkeit innerhalb des C-Programms das Programm zu rufen, via Pipe aus dessen stdout zu lesen und die jeweiligen Zeilen zu interpretieren. So k&ouml;nnte man zum Anwendungsnamen der Anwendung kommen, die auf den gefunden Port lauscht.<\/p>\n<p>Ich hoffe noch, dass es eine einfachere M&ouml;glichkeit unter Linux gibt (bspw. einen Systemcall, der direkt befragt werden kann). Dennoch haben wir nun herausgefunden, wie man Pakete am Netzwerkger&auml;t mitlauscht und sich den Anwendungsnamen der Anwendung holt, mit der gerade gesprochen wird, bzw. die gerade spricht.<\/p>\n<p>* pcap h&auml;lt sich offenbar nicht an das Ethernet-Framelayout. Die Gesamtl&auml;nge des Ethernet Header ist zwar unver&auml;ndert, allerdings stehen nicht&nbsp;Quell- und Ziel-MAC-Adresse vorn, sondern es stehen 6 Byte Informationen, dann die Quell-MAC-Adresse und dann 2 (offenbar ungenutzte) Byte und 2 Byte, die das dar&uuml;ber liegende Protokoll anzeigen. In den ersten 6 Byte ist offenbar ebenfalls encodiert, ob das Paket von uns geschickt wurde, oder nicht. F&uuml;r weitere Informationen sollte WireShark angeworfen werden, der entsprechend das Layout anzeigt.**<\/p>\n<p>** Das Verhalten liegt offenbar nicht an pcap, sondern eher an Linux, was beim Schn&uuml;ffeln an \"any\"-Ger&auml;ten, einen anderen Paketaufbau zur&uuml;ckliefert. Schn&uuml;ffelt man hingegen \"nur\" an \"wlanX\" und \"ethX\", dann erh&auml;lt man einen normalen Ethernet-Frame zur&uuml;ck, der wie auf Wikipedia beschrieben, aufgebaut ist. Dann gibt es auch zwei MAC-Adressen im Ethernet-Header. Btw. ist zu Beachten, dass auf x64-Maschinen die Netzwerk Byte Order von der Host Byte Order abweicht (siehe Little \/ Big Endian). Es ist also notwendig bspw. bei IP-Adressen und Ports eine Variante von <em>htons<\/em> auszuf&uuml;hren<em>.<\/em><\/p>\n<p>[1]&nbsp;<a href=\"http:\/\/en.wikipedia.org\/wiki\/Ethernet_frame\">http:\/\/en.wikipedia.org\/wiki\/Ethernet_frame<\/a><br\/>\n[2]&nbsp;<a href=\"http:\/\/de.wikipedia.org\/wiki\/IP-Paket\">http:\/\/de.wikipedia.org\/wiki\/IP-Paket<\/a><br\/>\n[3]&nbsp;<a href=\"http:\/\/en.wikipedia.org\/wiki\/Transmission_Control_Protocol\">http:\/\/en.wikipedia.org\/wiki\/Transmission_Control_Protocol<\/a><\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"PHP - HTTP Extention installieren","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/php-http-extention-installieren.html","rel":"alternate"}},"published":"2015-04-29T18:20:00+02:00","updated":"2015-04-29T18:20:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-04-29:\/informatik\/php-http-extention-installieren.html","summary":"<p>F&uuml;r eine private Website schreibe ich an einem PHP-Skript, welches erkennen soll, ob eine URL noch aktiv ist oder nicht. Recht einfache Sache:<\/p>\n<ol>\n<li>rausschicken eines GET oder HEAD-Requests an den Server mit der entsprechenden URL<\/li>\n<li>wenn der Statuscode ein anderer als 200 ist, ist ein Fehler aufgetreten.<ul>\n<li>Mit 3XX-Fehlern kann \u2026<\/li><\/ul><\/li><\/ol>","content":"<p>F&uuml;r eine private Website schreibe ich an einem PHP-Skript, welches erkennen soll, ob eine URL noch aktiv ist oder nicht. Recht einfache Sache:<\/p>\n<ol>\n<li>rausschicken eines GET oder HEAD-Requests an den Server mit der entsprechenden URL<\/li>\n<li>wenn der Statuscode ein anderer als 200 ist, ist ein Fehler aufgetreten.<ul>\n<li>Mit 3XX-Fehlern kann man umgehen (i.d.R. ist die gesuchte Datei dann nur umgezogen)<\/li>\n<li>4XX Fehler deuten darauf hin, dass die Datei weg ist<\/li>\n<li>5XX Fehler deuten auf Serverfehler hin, dh. wahrscheinlich sp&auml;ter wieder auffindbar<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Bin dann auch gleich in der Dokumentation von PHP auf eine Funktion namens <em>http_get<\/em> gesto&szlig;en. Soweit so gut. Ausprobieren wollen, geht nicht. Er findet die Funktion nicht. Das ist nat&uuml;rlich ziemlich schade. Aber woran liegt das? Weitergesucht und herausgefunden, dass diese Funktion Teil einer PHP-Extention ist. N&auml;mlich pecl_http.<\/p>\n<p>Nun sucht man nat&uuml;rlich nach einer Installationsanleitung, nach M&ouml;glichkeit sogar nach einem Paket in der Paketverwaltung der Linux-Distribution. Letzteres ist v&ouml;llig sinnlos, denn anstelle die Paketverwaltung zu verwenden, verwendet PHP f&uuml;r die Erweiterungen ein eigenes System, welches den Quellcode selbst baut, linkt und dann auf den System platziert.<\/p>\n<p>Wie also genau kann man nun die Erweiterung installieren? Zun&auml;chst brauchen wir f&uuml;r diese Erweiterung einige Pakete, darunter:<\/p>\n<ul>\n<li>libcurl3<\/li>\n<li>libpcre3-dev<\/li>\n<li>php5-dev <em>(um den pecl-Befehl zu haben)<\/em><\/li>\n<\/ul>\n<p>Installation mit:<\/p>\n<blockquote>\n<p>sudo apt-get install libpcre3-dev php5-dev libcurl3<\/p>\n<\/blockquote>\n<p>Nun installieren wir mal die http-Erweiterung:<\/p>\n<blockquote>\n<p>sudo pecl install pecl_http<\/p>\n<\/blockquote>\n<p>Nun l&auml;dt der pecl-Befehl die entsprechenden Quellcode-Dateien aus dem Internet herunter und baut sie. Dazu m&uuml;ssen wir die Orte f&uuml;r bestimmte Bibliotheken angeben, bspw. libevent, ich habe das einfach abgenickt (pecl vermutet diese Dateien unter \/usr).<\/p>\n<p>Gebaut und auf dem System sind die Dateien nun. Nun m&uuml;ssen wir noch die Extension aktivieren. Dazu gehen wir nach \/etc\/php5\/*\/php.ini, wobei * bspw. f&uuml;r apache2 oder auch cli stehen kann. Dort suchen wir nach dem Begriff \"extension=\", treffen auf einen Kommentar, darunter f&uuml;gen wir folgende Zeilen ein:<\/p>\n<blockquote>\n<p>extension=raphf.so<br\/>\nextension=propro.so<br\/>\nextension=http.so<\/p>\n<\/blockquote>\n<p>Die pecl_http-Erweiterung der Version 2 unterst&uuml;tzt aber die og. Funktion garnicht mehr. Dh. alles f&uuml;r die Katz. Naja fast - bis ich entsprechende Methoden \/ Objekte in der neuen API [1] finde, die den gew&uuml;nschten Zweck erf&uuml;llen k&ouml;nnen.<\/p>\n<p>[1]&nbsp;http:\/\/devel-m6w6.rhcloud.com\/mdref\/http<\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"Seminararbeit: x264 als Benchmark","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/seminararbeit-x264-als-benchmark.html","rel":"alternate"}},"published":"2015-03-07T14:01:00+01:00","updated":"2015-03-07T14:01:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2015-03-07:\/informatik\/seminararbeit-x264-als-benchmark.html","summary":"<p>Wenn auch etwas sp&auml;t, will ich hier auf meine ver&ouml;ffentlichte Seminararbeit zum Thema \"x264 als Benchmark\" aufmerksam machen. Die Arbeit zeigt, wie der TurboTUC der Technischen Universit&auml;t Chemnitz bei einem Benchmarkskript abschneidet. Au&szlig;erdem l&auml;sst die Testanordnung Schl&uuml;sse auf die Sinnhaftigkeit von OpenCL und Vektorinstruktion in der konkreten Implementierung in x264 \u2026<\/p>","content":"<p>Wenn auch etwas sp&auml;t, will ich hier auf meine ver&ouml;ffentlichte Seminararbeit zum Thema \"x264 als Benchmark\" aufmerksam machen. Die Arbeit zeigt, wie der TurboTUC der Technischen Universit&auml;t Chemnitz bei einem Benchmarkskript abschneidet. Au&szlig;erdem l&auml;sst die Testanordnung Schl&uuml;sse auf die Sinnhaftigkeit von OpenCL und Vektorinstruktion in der konkreten Implementierung in x264 zu.<\/p>\n<p><a href=\"http:\/\/www.qucosa.de\/fileadmin\/data\/qucosa\/documents\/15963\/x264_benchmark.pdf\">x264 als Benchmark (qucosa)<\/a><\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"Mitschriften zum Infoevent \"Fortschreibung des Nahverkehrsplans\" vom 27.11.2014","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/mitschriften-zum-infoevent-fortschreibung-des-nahverkehrsplans-vom-27-11-2014.html","rel":"alternate"}},"published":"2014-11-30T18:46:00+01:00","updated":"2014-11-30T18:46:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-11-30:\/sonstiges\/mitschriften-zum-infoevent-fortschreibung-des-nahverkehrsplans-vom-27-11-2014.html","content":"<p>Am 27.11.2014 war eine Infoveranstaltung zur Fortschreibung des Nahverkehrsplans f&uuml;r die Stadt Chemnitz. Anbei k&ouml;nnen meine Mitschriften zu dem Event gefunden werden. Das ist KEIN Wortprotokoll.<\/p>\n<p><a href=\"\/static\/resources\/2014-11-fortschreibung-nahverkehr.pdf\">Fortschreibung des Nahverkehrsplans<\/a><\/p>","category":[{"@attributes":{"term":"Sonstiges"}},{"@attributes":{"term":"\u00d6PNV"}},{"@attributes":{"term":"Bus"}},{"@attributes":{"term":"Bahn"}},{"@attributes":{"term":"Nahverkehr"}},{"@attributes":{"term":"Chemnitzer Modell"}}]},{"title":"Informationsveranstaltung zur Fortschreibung des Nahverkehrsplans von Chemnitz","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/informationsveranstaltung-zur-fortschreibung-des-nahverkehrsplans-von-chemnitz.html","rel":"alternate"}},"published":"2014-11-18T18:02:00+01:00","updated":"2014-11-18T18:02:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-11-18:\/sonstiges\/informationsveranstaltung-zur-fortschreibung-des-nahverkehrsplans-von-chemnitz.html","summary":"<p>Nur kurz der Hinweis, dass am 27.11.2014 im Rathaus die dritte Informationsveranstaltung zur Fortschreibung des Nahverkehrsplans von Chemnitz stattfinden soll. Die Veranstaltung geht von 18:00 bis 20:00 Uhr und soll im Stadtverordnetensaal im Rathaus der Stadt Chemnitz (Am Markt 1).<\/p>\n<p>Quelle: <a href=\"http:\/\/chemnitz.de\/chemnitz\/de\/aktuelles\/presse\/pressemitteilungen\/2014\/624.html\">http:\/\/chemnitz.de\/chemnitz\/de \u2026<\/a><\/p>","content":"<p>Nur kurz der Hinweis, dass am 27.11.2014 im Rathaus die dritte Informationsveranstaltung zur Fortschreibung des Nahverkehrsplans von Chemnitz stattfinden soll. Die Veranstaltung geht von 18:00 bis 20:00 Uhr und soll im Stadtverordnetensaal im Rathaus der Stadt Chemnitz (Am Markt 1).<\/p>\n<p>Quelle: <a href=\"http:\/\/chemnitz.de\/chemnitz\/de\/aktuelles\/presse\/pressemitteilungen\/2014\/624.html\">http:\/\/chemnitz.de\/chemnitz\/de\/aktuelles\/presse\/pressemitteilungen\/2014\/624.html<\/a><\/p>","category":[{"@attributes":{"term":"Sonstiges"}},{"@attributes":{"term":"\u00d6PNV"}},{"@attributes":{"term":"Bus"}},{"@attributes":{"term":"Bahn"}},{"@attributes":{"term":"Nahverkehr"}},{"@attributes":{"term":"Chemnitzer Modell"}}]},{"title":"Mitschriften zum Infoevent zur Stufe 2 des Chemnitzer Modells","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/mitschriften-zum-infoevent-zur-stufe-2-des-chemnitzer-modells.html","rel":"alternate"}},"published":"2014-11-13T20:31:00+01:00","updated":"2014-11-13T20:31:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-11-13:\/sonstiges\/mitschriften-zum-infoevent-zur-stufe-2-des-chemnitzer-modells.html","content":"<p>Am Mittwoch, den 12.11.2014, war eine B&uuml;rgerversammlung \/ Informationsveranstaltung zum Thema Stufe 2 des Chemnitzer Modells. Dabei geht es um den Umbau der Reichenhainer Stra&szlig;e und die Anbindung der neuen Stra&szlig;enbahntrasse an die Eisenbahnstrecke nach Thalheim.<\/p>\n<p><a href=\"\/static\/resources\/2014-11-chemnitzer_modell.pdf\">Mitschriften zur Infoveranstaltung zum Chemnitzer Modell Stufe 2<\/a><\/p>","category":[{"@attributes":{"term":"Sonstiges"}},{"@attributes":{"term":"Chemnitzer Modell"}},{"@attributes":{"term":"CVAG"}},{"@attributes":{"term":"Linie 3"}},{"@attributes":{"term":"\u00d6PNV"}},{"@attributes":{"term":"Reichenhainer Stra\u00dfe"}},{"@attributes":{"term":"Umbau"}},{"@attributes":{"term":"VMS"}}]},{"title":"Infoveranstaltung zum Chemnitzer Modell Stufe 2","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/infoveranstaltung-zum-chemnitzer-modell-stufe-2.html","rel":"alternate"}},"published":"2014-11-12T13:54:00+01:00","updated":"2014-11-12T13:54:00+01:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-11-12:\/sonstiges\/infoveranstaltung-zum-chemnitzer-modell-stufe-2.html","content":"<p>Heute Abend (am 12.11.) wird um 19:00 bis 21:00 Uhr eine Informationsveranstaltung im Zentralen H&ouml;rsaalgeb&auml;ude (Orangerie), im Raum N114 stattfinden. Dort soll den B&uuml;rgern das Chemnitzer Modell Stufe 2 erkl&auml;rt werden.<\/p>\n<p>Weitere Informationen: <a href=\"http:\/\/chemnitz.de\/chemnitz\/de\/aktuelles\/publikationen\/amtsblatt\/2014\/44.html\" title=\"Weitere Informationen\">Amtsblatt<\/a><\/p>","category":[{"@attributes":{"term":"Sonstiges"}},{"@attributes":{"term":"\u00d6PNV"}},{"@attributes":{"term":"Bus"}},{"@attributes":{"term":"Bahn"}},{"@attributes":{"term":"Nahverkehr"}},{"@attributes":{"term":"Chemnitzer Modell"}}]},{"title":"Firefox AddOn selbst entwickeln","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/firefox-addon-selbst-entwickeln.html","rel":"alternate"}},"published":"2014-09-18T18:01:00+02:00","updated":"2014-09-18T18:01:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-09-18:\/informatik\/firefox-addon-selbst-entwickeln.html","summary":"<p>Heute habe ich mich mal kurz mit Firefox-AddOns besch&auml;ftigt. Idee war es ein AddOn zu schaffen, was die Youtube-Suchleiste (die beim runterscrollen auf dem Bildschirm bleibt) das CSS-Attribut \"position=absolute\" zu geben, und damit zu verhindern, dass die Leiste mit nach unten scrollt.<\/p>\n<p>Um Firefox-AddOns zu entwickeln muss man sich \u2026<\/p>","content":"<p>Heute habe ich mich mal kurz mit Firefox-AddOns besch&auml;ftigt. Idee war es ein AddOn zu schaffen, was die Youtube-Suchleiste (die beim runterscrollen auf dem Bildschirm bleibt) das CSS-Attribut \"position=absolute\" zu geben, und damit zu verhindern, dass die Leiste mit nach unten scrollt.<\/p>\n<p>Um Firefox-AddOns zu entwickeln muss man sich zuerst das AddOn-SDK von Mozilla herunterladen [1]. Damit das SDK funktioniert ben&ouml;tigt ihr Python und den Firefox selbst! Das Archiv entpacken, und das Bash-Skript \"bin\/activate\" ausf&uuml;hren. Dann seid ihr in der SDK-Umgebung (mit eurer Bash). Dann k&ouml;nnte eure Bash folgendes anzeigen:<\/p>\n<blockquote>\n<p>(addon-sdk-1.17)snaums\\@xlifebook:\\~\/Desktop\/addon-sdk-1.17\\$<\/p>\n<\/blockquote>\n<p>Nun k&ouml;nnt ihr das cfx-Skript ausf&uuml;hren. Mit <em>cfx --help<\/em> k&ouml;nnt ihr wichtige Funktionen des Skriptes herausfinden. Zum Beispiel legt <em>cfx init<\/em> in einem leeren Verzeichnis ein Beispiel-Addon an, was nichts tut. Ihr erhaltet dabei die Ordner \"data\", \"lib\" und \"test\". In \"data\" geh&ouml;ren zum Beispiel Bilder, die ihr in eurem AddOn verwenden wollt, \"lib\" enth&auml;lt die Codedatei(en) und \"test\" enth&auml;lt den Code f&uuml;r die Tests eures AddOns. Mit <em>cfx run<\/em> &ouml;ffnet sich ein Test-Firefox, welches euer AddOn installiert hat. Damit k&ouml;nnt ihr die Funktionsweise eures AddOns &uuml;berpr&uuml;fen. Und mit <em>cfx test<\/em> lasst ihr das Testskript unter \/test\/... laufen. Die Tests m&uuml;sst ihr &uuml;brigens selbst schreiben.<\/p>\n<p>Mit <em>cfx xpi<\/em> k&ouml;nnt ihr aus eurem Code eine .xpi-Datei machen, die ihr in eurem Firefox einf&uuml;gen k&ouml;nnt und damit euer neues AddOn installiert. Die Datei package.json, die beim init angelegt worden ist, enth&auml;lt &uuml;brigens Namen und weitere Informationen &uuml;ber euer AddOn, unter anderem auch, ob es im privaten Modus laufen darf oder nicht. (siehe [2])<\/p>\n<p>Die AddOns f&uuml;r den Firefox werden (neuerdings) in Javascript entwickelt, das hei&szlig;t ihr solltet gute Javascript-Kenntnisse haben. Euch hilft auch das Mozilla Developer Network, mit einigen kleineren Beispielen, die eine gewisse Funktionalit&auml;t liefern, die in eurem AddOn sicher sinnvoll w&auml;ren.<\/p>\n<p>Mein kleines AddOn soll nichts anderes machen, als verhindern, dass die Youtube-Suchleiste mitscrollt. Ich klicke also im Browser mit Rechtsklick darauf, und auf \"Element untersuchen\". Nun suche die das \\&lt;div&gt;, was am weitesten oben steht, suche mit dessen ID heraus (masthead-positioner), und probiere in der Javascript-Konsole im Browser: <code>document.getElementById(\"masthead-positioner\").style.position=\"absolute\";<\/code>. Und siehe da - es funktioniert. Nun muss ich das nurnoch in mein AddOn bringen.<\/p>\n<p>Im Mozilla Developer Network lese ich, dass man f&uuml;r Seitenver&auml;nderungen mit bestimmten URLs das Modul <em>pageMod<\/em> verwenden soll. Schnell beim Beispiel abgeschrieben kommt nun folgendes heraus (lib\/main.js):<\/p>\n<div class=\"highlight\"><pre><span class=\"code-line\"><span><\/span><code><span class=\"kd\">var<\/span><span class=\"w\"> <\/span><span class=\"nx\">pageMod<\/span><span class=\"w\"> <\/span><span class=\"o\">=<\/span><span class=\"w\"> <\/span><span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"sdk\/page-mod\"<\/span><span class=\"p\">);<\/span><\/code><\/span>\n<span class=\"code-line\"><\/span>\n<span class=\"code-line\"><span class=\"nx\">pageMod<\/span><span class=\"p\">.<\/span><span class=\"nx\">PageMod<\/span><span class=\"p\">({<\/span><span class=\"w\">  <\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">include<\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"s2\">\"\\*.youtube.com\"<\/span><span class=\"p\">,<\/span><span class=\"w\">  <\/span><\/span>\n<span class=\"code-line\"><span class=\"nx\">contentScript<\/span><span class=\"o\">:<\/span><span class=\"w\"> <\/span><span class=\"s1\">'if (document.getElementById(\"masthead-positioner\")!=null) { '<\/span><span class=\"w\"> <\/span><span class=\"o\">+<\/span><span class=\"w\">  <\/span><\/span>\n<span class=\"code-line\"><span class=\"w\">    <\/span><span class=\"s1\">'document.getElementById(\"masthead-positioner\").style.position=\"absolute\"; }'<\/span><span class=\"w\">  <\/span><\/span>\n<span class=\"code-line\"><span class=\"p\">});<\/span><\/span>\n<span class=\"code-line\"><\/span><\/pre><\/div>\n<p>Das AddOn ist unter [3] erh&auml;ltlich.<\/p>\n<p>[1] <a href=\"https:\/\/developer.mozilla.org\/en-US\/Add-ons\/SDK\/Tutorials\/Installation\">https:\/\/developer.mozilla.org\/en-US\/Add-ons\/SDK\/Tutorials\/Installation<\/a><br\/>\n[2] <a href=\"https:\/\/developer.mozilla.org\/en-US\/Add-ons\/SDK\/Tools\/package_json\">https:\/\/developer.mozilla.org\/en-US\/Add-ons\/SDK\/Tools\/package_json<\/a><br\/>\n[3] <a href=\"https:\/\/addons.mozilla.org\/de\/firefox\/addon\/yt-heading-fixer\/\">https:\/\/addons.mozilla.org\/de\/firefox\/addon\/yt-heading-fixer\/<\/a><\/p>","category":{"@attributes":{"term":"Informatik"}}},{"title":"\"Oettinger Games gegen Rechts\" ein voller Erfolg","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/oettinger-games-gegen-rechts-ein-voller-erfolg.html","rel":"alternate"}},"published":"2014-08-29T07:47:00+02:00","updated":"2014-08-29T07:47:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-08-29:\/sonstiges\/oettinger-games-gegen-rechts-ein-voller-erfolg.html","summary":"<p>Die Aktion \"Oettinger Games gegen Rechts\", die das Ziel hatte Nazis aus Deutschland und anderen Gebieten Europas und Nordafrikas zu vertreiben, war ein voller Erfolg. So konnten die Wehrmacht-Streitkr&auml;fte mehrfach erfolgreich zur&uuml;ckgeschlagen werden, sie wurden oft sabotiert und generell bleibt nichts mehr von den Nazi-Soldaten &uuml;brig. In f&uuml;nf Spielreviews und \u2026<\/p>","content":"<p>Die Aktion \"Oettinger Games gegen Rechts\", die das Ziel hatte Nazis aus Deutschland und anderen Gebieten Europas und Nordafrikas zu vertreiben, war ein voller Erfolg. So konnten die Wehrmacht-Streitkr&auml;fte mehrfach erfolgreich zur&uuml;ckgeschlagen werden, sie wurden oft sabotiert und generell bleibt nichts mehr von den Nazi-Soldaten &uuml;brig. In f&uuml;nf Spielreviews und drei Videos k&ouml;nnen die Schlachten nachvollzogen werden:<\/p>\n<ul>\n<li><a class=\"editor_link extern_link\" href=\"http:\/\/oettingergames.de\/index.php?position=game&amp;action=detail&amp;id=12\">Call of Duty Finest Hour (PS2 und Gamecube)<\/a><\/li>\n<li><a class=\"editor_link extern_link\" href=\"http:\/\/oettingergames.de\/index.php?position=game&amp;action=read&amp;text_id=141\">Call of Duty 5 World At War Windows Review<\/a><\/li>\n<li><a class=\"editor_link extern_link\" href=\"http:\/\/oettingergames.de\/index.php?position=game&amp;action=read&amp;text_id=142\">Medal of Honor European Assault PS2 Review<\/a><\/li>\n<li><a class=\"editor_link extern_link\" href=\"http:\/\/oettingergames.de\/index.php?position=game&amp;action=read&amp;text_id=138\">Medal of Honor Frontline PS3 Review<\/a><\/li>\n<li><a class=\"editor_link extern_link\" href=\"http:\/\/oettingergames.de\/index.php?position=game&amp;action=read&amp;text_id=144\">Medal of Honor Underground<\/a><\/li>\n<li><a class=\"editor_link extern_link\" href=\"http:\/\/oettingergames.de\/index.php?position=game&amp;action=read&amp;text_id=143\">Turning Point: Fall of Liberty Windows Review<\/a><\/li>\n<\/ul>\n<!-- -->\n<ul>\n<li><a class=\"magnific-popup-youtube extern_link_youtube\" href=\"http:\/\/www.youtube.com\/watch?v=CDAngVPNiy8\">Medal of Honor Frontline Trailer<\/a><\/li>\n<li><a class=\"magnific-popup-youtube extern_link_youtube\" href=\"http:\/\/www.youtube.com\/watch?v=YPVc3I_A4xw\">Medal of Honor European Assault - Dogs of War Trailer<\/a><\/li>\n<li><a class=\"magnific-popup-youtube extern_link_youtube\" href=\"http:\/\/www.youtube.com\/watch?v=KnSWjAhOT1w\">Medal of Honor Underground Trailer<\/a><\/li>\n<\/ul>\n<p>Damit ist der Weg f&uuml;r die Landtagswahl in Sachsen am Sonntag, den 31. August, wohl klar. Lasst uns auch da Nazis keine Chance und keinen Platz im Parlament geben.<\/p>","category":{"@attributes":{"term":"Sonstiges"}}},{"title":"Oettinger Games gegen Rechts","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/oettinger-games-gegen-rechts.html","rel":"alternate"}},"published":"2014-08-17T19:59:00+02:00","updated":"2014-08-17T19:59:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-08-17:\/sonstiges\/oettinger-games-gegen-rechts.html","summary":"<p>Hallo.<\/p>\n<p>Oettinger Games bekennt sich nun klar gegen Rechts, und bek&auml;mpft offensiv Nazis. In der Woche vom 25. bis 31. August wird Deutschland mehrfach von Nazis befreit. Begleitet werden die allierten Truppen von Kameras, die in meist Ego-Perspektive aufzeichnen, was passiert ist und der Nachwelt erhalten sollen.<\/p>\n<p>Angesichts der kommenden \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>Oettinger Games bekennt sich nun klar gegen Rechts, und bek&auml;mpft offensiv Nazis. In der Woche vom 25. bis 31. August wird Deutschland mehrfach von Nazis befreit. Begleitet werden die allierten Truppen von Kameras, die in meist Ego-Perspektive aufzeichnen, was passiert ist und der Nachwelt erhalten sollen.<\/p>\n<p>Angesichts der kommenden Landtagswahl am 31. August in Sachsen halte ich es f&uuml;r angebracht gegen Nazis vorzugehen, wozu ich hiermit meinen Teil beitrage, ohne Gefahr zu laufen zu sehr verletzt zu werden. Ich sehe es als einfachen Weg mit Nazis abzuschlie&szlig;en und eine gerechte, inklusive und tolerante Welt zu schaffen, die Menschen so akzeptiert, wie sie sind und nicht aufgrund von Religionen, Herkunft oder Geschlecht &uuml;ber sie entscheiden muss.<\/p>\n<p>Deshalb am 31. August Piraten W&auml;hlen.<\/p>","category":{"@attributes":{"term":"Sonstiges"}}},{"title":"HTTP-Server Update #1","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/http-server-update-1.html","rel":"alternate"}},"published":"2014-08-03T18:32:00+02:00","updated":"2014-08-03T18:32:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-08-03:\/informatik\/http-server-update-1.html","summary":"<p>Hallo.<\/p>\n<p>Nachdem ich vorgestern meinen Webserver mit Threads ausgestattet habe und die Threads per Linux-Semaphoren blockbar gemacht habe, habe ich noch einige weitere &Auml;nderungen hinzugef&uuml;gt. Zum einen wird nun der Content-Type und die Content-Length ordnungsgem&auml;&szlig; zur&uuml;ckgegeben. Die Content-Length gibt die L&auml;nge des HTTP-Bodies an, der Content-Type gibt den MIME-Typ des \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>Nachdem ich vorgestern meinen Webserver mit Threads ausgestattet habe und die Threads per Linux-Semaphoren blockbar gemacht habe, habe ich noch einige weitere &Auml;nderungen hinzugef&uuml;gt. Zum einen wird nun der Content-Type und die Content-Length ordnungsgem&auml;&szlig; zur&uuml;ckgegeben. Die Content-Length gibt die L&auml;nge des HTTP-Bodies an, der Content-Type gibt den MIME-Typ des Bodies an (zum Beispiel text\/html oder image\/png). Da im Moment fast nur statische HTML-Dateien unterst&uuml;tzt werden, ergibt sich der MIME-Type des Inhalts aus der Dateiendung der zu lesenden Datei, und die L&auml;nge ist die Dateigr&ouml;&szlig;e. Eine Abweichung gibt es allerdings, so wird PHP de facto bereits gerufen und die Ausgabe von PHP durch den Socket zur&uuml;ckgeschrieben. Allerdings geben die PHP-Testskripte keine Ausgaben zur&uuml;ck, die auch mit anderen Webservern wie Apache2 reproduzierbar w&auml;ren, sondern werden offenbar teilweise nicht ausgef&uuml;hrt sondern Teilskripte werden &uuml;bertragen. Das sollte nat&uuml;rlich auf garkeinen Fall passieren.<\/p>\n<p>Im aktuellen Zustand des Servers kann er bereits gespeicherte Websiten (getestet habe ich das mit der Startseite der Homepage der Technischen Universit&auml;t Chemnitz), welche fast komplett richtig angezeigt wurde, allerdings konnten offenbar die Javascript-Dateien nicht &uuml;bertragen werden, was zu kleineren Problemen f&uuml;hrte. Es wurden aber die CSS, sowie die Bilddateien erfolgreich &uuml;bertragen und konnten vom Browser angezeigt werden.<\/p>\n<p>Wie wird der Content-Type ermittelt? Ich habe mir ein simples Dateiformat &uuml;berlegt, welches den Dateiendungen den entsprechenden MIME-Types zuordnet. Beim Start des Servers wird die Datei eingelesen und alphabetisch sortiert (wie in der Datei) in ein Array geschrieben. &Uuml;ber dieses Array ist nun eine bin&auml;re Suche m&ouml;glich, was es mir erm&ouml;glicht relativ schnell auch bei gro&szlig;en Datenmengen und verschiedenen Dateitypen die richtige Zuordnung zu finden.<\/p>\n<p>Als n&auml;chtes versuche ich die HTTP-Aktionen (GET, POST, HEAD, DELETE, ... ) zu unterst&uuml;tzen und so vielleicht sogar einen kleinen Dateimanager &uuml;ber HTTP zu implementieren. Desweiteren soll der Server HTCPCP (Hypertext Coffeepot Control-Protocol) unterst&uuml;tzen. Langfristiges Ziel soll es sein, einen generischen Webserver zu implementieren, der sowohl Interpreter wie Python oder PHP starten kann, als auch C-Programme, die f&uuml;r irgendwelche Funktionen zust&auml;ndig sind. So soll es mir m&ouml;glich werden, C-Programme zu schreiben, die HTML zur&uuml;ckliefern, sodass der Server diesen Code zur&uuml;ckgeben kann. Damit erhoffe ich mir einen erheblichen Geschwindigkeitsgewinn in der Seitenauslieferung als mit PHP oder Python. Au&szlig;erdem muss am Speichermanagment des Servers gearbeitet werden, da er nicht den gesamten angeforderten Speicher ordentlich wieder freigibt. Daf&uuml;r wird sich sicherlich noch eine L&ouml;sung finden.<\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"HTTP"}},{"@attributes":{"term":"Server"}},{"@attributes":{"term":"Thread"}}]},{"title":"HTTP-Server mit Threads","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/informatik\/http-server-mit-threads.html","rel":"alternate"}},"published":"2014-08-01T14:14:00+02:00","updated":"2014-08-01T14:14:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-08-01:\/informatik\/http-server-mit-threads.html","summary":"<p>Hallo.<\/p>\n<p>HTTP ist das Protokoll, was f&uuml;r das Web (gemeint ist, Webseiten, die im Browser angezeigt werden), Verwendung findet. HTTP ist relativ simpel aufgebaut, allerdings doch etwas schwieriger als Gopher [1]. Vor etwa einem halben Jahr habe ich einen minimalistischen Gopher-Clienten geschrieben, kurz darauf einen Parser, der HTTP versteht und \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>HTTP ist das Protokoll, was f&uuml;r das Web (gemeint ist, Webseiten, die im Browser angezeigt werden), Verwendung findet. HTTP ist relativ simpel aufgebaut, allerdings doch etwas schwieriger als Gopher [1]. Vor etwa einem halben Jahr habe ich einen minimalistischen Gopher-Clienten geschrieben, kurz darauf einen Parser, der HTTP versteht und eine Datenstruktur, die ein ebenfalls etwa in der Zeit entstandener minimalistischer HTTP-Server f&uuml;llen kann und senden kann.<\/p>\n<p>Heute habe ich diesen Prototyp durch Threads erweitert. Wenn ich diesem Webserver nun zwinge ein Bash-Kommando abzusetzen, was PHP oder andere Skriptsprachen-Interpreter ruft und die Ausgaben zur&uuml;ckgibt, dann k&ouml;nnte ich theoretisch Oettinger Games auf diesen Webserver umziehen. Dazu muss dann auch ein vServer her. H&auml;tte nat&uuml;rlich den Nachteil, dass der HTTP-Server im Moment noch garnicht konfigurierbar ist, also weder Threadzahl, noch was wie dargestellt wird und wann der Server wegen &Uuml;berlast abriegelt.<\/p>\n<p>Als n&auml;chstes sollten Konfigurationsdateien hinzugef&uuml;gt werden. Dh. einen Parser schreiben und ggf. ein Programmteil, der die aktuellen Konfiguration abspeichern kann. Startparameter, die die geparsten Konfigurationen &uuml;berschreiben, sind mit Sicherheit auch nicht schlecht. Danach fange ich wahrscheinlich an, ein Framework in C++ zu schreiben, um Webseiten, die von meinem Server aufgerufen werden in C++ zu verfassen. Darunter w&uuml;rden dann solche angenehmen Dinge kommen wie MySQL-Anbindung und irgendeine Abstraktion von HTML und Javascript sowie Konfigurationsdateien davon.<\/p>\n<p>Ich bleib mal gespannt, was sich da noch tun wird.<\/p>\n<p>[1] http:\/\/de.wikipedia.org\/wiki\/Gopher<\/p>","category":[{"@attributes":{"term":"Informatik"}},{"@attributes":{"term":"HTTP"}},{"@attributes":{"term":"Server"}},{"@attributes":{"term":"Thread"}}]},{"title":"SummerGamesDoneQuick","link":{"@attributes":{"href":"https:\/\/www.snaums.de\/sonstiges\/summergamesdonequick.html","rel":"alternate"}},"published":"2014-06-13T20:17:00+02:00","updated":"2014-06-13T20:17:00+02:00","author":{"name":"snaums"},"id":"tag:www.snaums.de,2014-06-13:\/sonstiges\/summergamesdonequick.html","summary":"<p>Hallo.<\/p>\n<p>Ganz anders als sonst, will ich hier nur kurz auf eine Veranstaltung bez&uuml;glich Gaming aufmerksam machen. SpeedDemosArchive veranstaltet vom 22. bis 28. Juni das Charity-Event Summer Games Done Quick 2014, wo Speedrunner aus aller Welt (haupts&auml;chlich USA ;) ) Spiele speedrunnen und dabei viele nette Tricks dem unbedarften Zuschauer offenbaren. So \u2026<\/p>","content":"<p>Hallo.<\/p>\n<p>Ganz anders als sonst, will ich hier nur kurz auf eine Veranstaltung bez&uuml;glich Gaming aufmerksam machen. SpeedDemosArchive veranstaltet vom 22. bis 28. Juni das Charity-Event Summer Games Done Quick 2014, wo Speedrunner aus aller Welt (haupts&auml;chlich USA ;) ) Spiele speedrunnen und dabei viele nette Tricks dem unbedarften Zuschauer offenbaren. So ist die Zeit, die ein Spiel braucht zwar auch wichtig, aber im Mittelpunkt des Events steht der Spa&szlig; und, dass bei dem Event Spenden f&uuml;r Doctors Without Borders (&Auml;rzte ohne Grenzen) und Prevent Cancer (Krebsvorsorge-Organisation) gesammelt werden. Schaut mal mit rein, spendet, wenn ihr wollt, einen Betrag und habt Spa&szlig; dabei.<\/p>\n<p>MfG<\/p>","category":{"@attributes":{"term":"Sonstiges"}}}]}