Short build instructions Edit
- Use Mercurial (hg) to checkout a copy of the sources from http://bitbucket.org/hudson/magic-lantern/
hg clone https://bitbucket.org/hudson/magic-lantern/
- after the clone, enter the magic-latern directory and call "hg update" to choose the branch to work on (e.g. hg update unified for the unified branch).
- Install or build the arm-elf cross compile environment (gcc 4.6.2) and perl.
- Update the Makefile.inc $(ARM_PATH) to point to your arm-elf-gcc (arm-linux-gcc will work as well).
- Run make. There are more warnings than there should be; a good janitor project would be to clean up all of the warnings with explicit typecasts or fixes.
- If there are errors, run make V=1 2>&1 | tee /tmp/make.log and send the logfile to the devel list for analysis.
- If you are building under Cygwin rather than Linux or OS X, here's a nickel...
Click the link above to find out how to setup the compiler, how to solve common problems etc.
Some juicy detailsEdit
magiclantern ELF image Edit
The build process for the firmware involves a few non-traditional steps compared to a normal compilation. This section tries to walk through the process with emphasis on how it differs from a regular executable Makefile.
- If the generate-font program is newer than the font-*.in files, it is run to create the text files from the X11 fonts. This typically is not run since the font-*.in files are checked in and not everyone has the bigtext program to create the text files.
- The fonts are generated from the font-*.in files using the mkfont program that I've written. This perl script translates the ASCII art images of the fonts into static C structures that represent the bitmap fonts. There is some hackery involved using C99 designated initializers and strided representation of the fonts to avoid dependencies on the number of rows per character, which varies by font.
Object files Edit
- All of the object files that make up the new firmware, including the font-*.c files, are cross-compiled normally to produce .o files.
- The version.c file is generated every build with information as to who, when, where and what mercurial version was used for compiling.
- The 5d2-stubs.110.S file is compiled to produce an empty .o file that has symbols for the DryOS functions that are declared extern in dryos.h. The NSTUB() macro does some magic to produce symbols at a given offset, effectively treating the camera's ROM image as a library that can be called into from the magiclantern code.
Initial Linking Edit
- The linker script in magiclantern.lds.S is run through cpp to replace the starting address (RESTARTSTART), which is selected to be just above the end of the DryOS BSS. This address can be located for future versions of Canon's firmware in the zero_bss() loop soon after init.
- Also in the script are several dynamic sections for tasks overrides, auto task starts and init functions. These sections allow modules to dynamically add new tasks to be run without modification to the magiclantern startup code using the TASK_CREATE(), TASK_OVERRIDE() and INIT_FUNC() macros in task.h.
- The magiclantern BSS follows the data segment and the _bss_end address is used to set the DryOS reserved heap space so that the Canon software won't use the magiclantern code and data segments for its own allocation.
Reboot shim Edit
- The magiclantern ELF image is then run through objcopy to produce a raw binary named magiclantern.bin of just the text+code sections.
- The reboot.c file contains the actual exploit code that orchestrates an orderly restart of the camera. It enters supervisor mode, reinitializes all of the ARM memory regions, sets up caches.
- Also included in the reboot.c is inline assembly that does a .incbin of the magiclantern.bin file. This is stored at blob_start and runs through to blob_end.
- Due to an unfixed, but low priority bug in the linking of the reboot shim, all addresses have a 0x120 byte offset due to the Canon firmware header. The only memory reference in the shim is to the blob, so those addresses are fixed up by hand.
- The reboot shim is linked as normal with an entry of 0x800000, although there is a warning that the entry point can't be found.
Firmware file Edit
- The reboot shim ELF image, with the included binary blob image of the Magic Lantern firmware, is run through objcopy produce a binary blob named reboot.bin
- This is then inserted into an legitimate, but empty, firmware file at offset 0x120 by the assemble_fw script. This reuses the existing header, which has the checksum updated to reflect the insertion of the new reboot shim.
- Product ID is 0x80000218 for 5D Mark II and 0x80000250 for the 7D.
Distribution zip file Edit
- The 'make zip' target will generate a zipfile with the firmware, a default configuration file and cropmarks bitmap.
- The zip.txt file is used to generate the extraction text.
Make targets Edit
- Typically only 'make' is needed. The default target is magiclantern.fir.
- The makefile uses a macro named $(build) to hide the messy compile lines used to build everything. If the environment variable V=1, then all the commands will be printed instead of the short lines.
- 'make clean' will remove all of the generated files
- 'make 5d2_dumper.fir' will generate a program that will dump the ROM image. It requires a 1.0.7 firmware flasher image, which is not distributed as part of Magic Lantern since it is copyright Canon.
- 'make install' is a convenience target for my Macbook with a CF card reader. You may need to update it for the path to you card reader, or you can just copy the files by hand.
Dependency tracking Edit
- There is no 'make depend' step required. The gcc -Wp,-MMD option is used to generate dependencies on the fly into .$@.d for each compilation target $@. The last line of the Makefile conditionally includes all of the .*.o.d files if they exist. On an initial build there are no .o files and no .o.d files, so all the files in the dependency for magiclantern will be compiled. After that build the dependency files will have been created and dependencies will be tracked.
- The dependency tracking is not as full-featured as the Linux kernel. If you change a compiler parameter like CFLAGS it is best to do a 'make clean' to ensure that all the files are rebuilt.
Extending Magic Lantern Edit
Magic Lantern is an open platform for digital 35mm cinema. We've tried to make it easy for new developers to add features to the system and extend the functionality that we've written.
- To add a file to the build list, just add the name of the .o to the dep list for the magiclantern target.
- If you want to create a task, add the TASK_CREATE() macro in your code. Look at zebra.c for an example of how to create a new task automatically. There are no dependencies to zebra.o elsewhere in the code, so if it is not linked in there will be no compilation failures.
- The DryOS RTOS is a pre-emptive scheduled multithreaded operating system. There is no memory protection (beyond the Canon ROM image), so it is possible to scribble over other threads' data, either intentionally or accidentally. Since the Magic Lantern firmware is running out of RAM, it is even possible to write self-modifying code (and both reboot.c and 5d-hack.c code make use of dynamic code generation to take control of the boot process). Typically, however, you do not want to write into your text segment.
- To sleep when your task is not doing anything, call msleep() with an integral number of microseconds to pause. Depending on the task priority, the sleep might be a bit longer than requested.
- To be notified via a callback when another task modifies a property, use prop_register_slave(). Look at lens.c to see how to hook the lens change events for examples.
- To modify a property, use prop_request_change(). Again, look at lens.h for how it adjusts the aperture and shutter speeds.
- To add a menu, call menu_add(). The exact syntax may change between released until the Magic Lantern API settles down.
- To draw text to the screen, use bmp_printf(). It is similar to the normal printf, but takes a fontspec which encodes the size, fg color and bg color, and an x/y bitmap vram coordinate. Embedded newlines ('\n') are correctly handled.
- To draw rectangles to the screen, you can use bmp_fill().
- Hooking keys is complicated. It requires creating a fake Canon dialog, which isn't fully understood yet.
- There are not any more complicated graphics drawing primitives yet. We need to either figure out how to use the Canon dialog API or create a full-featured graphics API.
See also this page (work on progress): Extending Magic Lantern