I searched for info about this but didn't find anything.
The idea is:
If I code a program in C, or any other languages, what else do I need to do for it to get recognized in BIOS and started by it as a DOS program or just a prompt program?
I got this idea after I booted an flash drive with windows using the ISO and Rufus, which put some code in the flash drive for the BIOS to recognize it and run, so I would like to do the same with a program of mine, for example.
Thanks in advance!
An interesting, but rather challenging exercise!
The BIOS will fetch a specific zone from the boot device, called a master boot record. In a "normal" situation with an OS and one or more partitions, the MBR will need to figure out where to find the OS, load that into memory, and pass control to it. At that time the regular boot sequence starts and somewhat later the OS will be running and be able to interact with you. More detail on the initial activities can be found here
Now, for educational purposes, this is not strictly necessary. You could write an MBR that just reads in a fixed part of the disk (the BIOS has functions that will allow you to read raw sectors off a disk, a disk can be considered as just a bunch of sectors each containing 512 bytes of information) and starts that code. You can find an open source MBR here and basically in any open source OS.
That was the "easy" part, because now you probably want to do something interesting. Unless you want to interact with each part of the hardware yourself, you will have to rely on the services provided by the BIOS to interact with keyboard, screen and disk. The traditionally best source about BIOS services is Ralf Brown's interrupt list.
One specific consideration: your C compiler comes with a standard library, and that library will need a specific OS for many of its operations (eg, to perform output to the screen, it will ask the operating system to perform that output, and the OS will typically use the BIOS or some direct access to the hardware to perform that task). So, in going the route explained above, you will also need to figure out a way to replace these services by some that use the BIOS and nothing more - ie, more or less rewrite the standard library.
In short, to arrive at something usable, you will be writing the essential parts of an operating system...
Actually BIOS is going to be dead in the next two years (INTEL will not support any BIOSes after this date) so you may want to learn UEFI standard. UEFI from v2.4 allows to write and add custom UEFI applications. (BTW the "traditional" BIOS settings on the UEFI computers is often implemented as a custom UEFI App).
Related
I trying to boot an elf microkernel in an UEFI environment. So i compiled a minimal boot loader and created an ESP image. This works fine if I boot via an HDD but I want to direct boot it via the qemu -kernel option (This is some special requirement as I am working with AMD SEV). This doesn't work.
I can boot my kernel like this with grub if I use grub mkimage with a fat image included i.e. like this:
mcopy -i "${basedir}/disk.fat" -- "${basedir}/kernel" ::kernel
mcopy -i "${basedir}/disk.fat" -- "${basedir}/module" ::module
grub-mkimage -O x86_64-efi
-c "${basedir}/grub-bootstrap.cfg"
-m "${basedir}/disk.fat"
-o "${basedir}/grub.efi"
But the goal for my system is minimalism and security hence the microkernel, so grub and it's vulnerabilities is out of question.
So my question is:
How to create a bootable application image similar to grub-mkimage?
I have read about efi stub boot but couldn't really figure out how to build an efi stub image.
Normally I am a bare metal embedded programmer, so the whole uefi boot thing is a bit weird to me. I am glad for any tips or recommendations. Also I figured stack overflow might not be the best place for such low level questions, can you maybe recommend other forums?
I want to direct boot it via the qemu -kernel option
Why? It's a qemu-specific hack that doesn't exist on anything else (including any real computer). By using this hack the only thing you're doing is failing to test anything you'd normally use to boot (and therefore failing to test anything that actually matters).
(This is some special requirement as I am working with AMD SEV)
That doesn't make any sense (it's a little bit like saying "I have a banana in my ear because I'm trying to learn how to play piano").
AMD's SEV is a set of extensions intended to enhance the security of virtual machines that has nothing at all to do with how you boot (or whether you boot from BIOS or UEFI or a qemu-specific hack).
I am glad for any tips or recommendations.
My recommendation is to stop using GRUB specific (multi-boot), Qemu specific (-kernel) and Linux/Unix specific (elf) tools and actually try to use UEFI. This will require you to write your own boot loader using (Microsoft's) PE32+ file format that uses UEFI's services itself. Note that GNU's tools (their "Gnu-EFI" stuff for GCC) is relatively awful (it puts a PE32+ wrapper around an ELF file and does run-time patching to make the resulting Franken-monster work); and there are much better alternatives now (e.g. the Clang/LLVM/lld toolchain).
If you care about security, then it'll also involve learning about UEFI SecureBoot (and key management, and digital signatures). If you care about secure virtual machines I'd also recommend learning about the SKINIT instruction from AMD"s manual (used to create a dynamic root of trust after boot); but don't forget that this is AMD specific and won't work on any Intel CPU, and is mostly obsolete (the "trusted measurement" stuff from BIOS and TPM was mostly superseded by SecureBoot anyway), and (even on Intel CPUs) if you're only the guest then the hyper-visor can emulate it in any way it wants (and it won't guarantee anything is secure).
Finally; note that booting a micro-kernel directly doesn't make much sense either. There's no device drivers in a micro-kernel; so after booting a micro-kernel you end up with a "can't start any device drivers because there are no device drivers" problem. Instead you need to load many files (e.g. maybe an initial RAM disk), then (e.g.) start some kind of "boot log handler" (to display error messages, etc); then find and start the kernel, then start other processes (e.g. "device manager" to detect devices and drivers; "VFS layer" to handle file systems and file IO; etc). For the whole thing; starting the kernel is just one relatively insignificant small step (not much more than starting a global shared library that provides multi-tasking) buried among a significantly larger amount of code that does all the work.
Sadly; booting a monolithic kernel directly can make sense because it can contain all the drivers (or at least, has enough built into the kernel's executable file to handle an initial RAM disk if it's "modular monolithic" with dynamically loaded drivers); and this "monolithic with stuff that doesn't belong in any micro-kernel" idea is what most beginner tutorials assume.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 2 years ago.
Improve this question
I programmed a little code for motion detection device(DA14531 SmartBond TINY module based on a CortexM0+) and I am having some experiments with it. at the end and after debugging and testing, I generated an ISO file and now I want to flash the device. Is the process similar to burning the ISO file on a USB flash or is the process different? I only have one device and I dont want to do something irreversible so I came here for some guidance first.
I looked online for a while but nothing matches my specifique situation, so providing me with the correct links is also helpful
The ISO 9660 format was designed for optical disks, using it is likely irrelevant to your use case, since there is IMHO a near to zero chance you will find a tool that will allow you to flash directly your program in a Cortex-M0+ device from a file in ISO 9660 format.
And if you may flash the ISO file as is in your Cortex-M0+ flash memory, your device will likely be unable to boot since it does rely on very specific information (stack pointer, first instruction to be executed) to be flashed in a verify specific location, not mentioning the waste of flash memory space this would cause.
That is, if Dialog documentation does not specifically mention the possibility of flashing a file in ISO 9660 format, this is likely (and not surprising) that this is not possible using Dialog software and hardware support tools.
So when you read the documentation for this product you noticed there is an SWD interface which is certainly one way into the part. When you further examined the pro kit and other solutions from them you see they mention segger jlink interfaces for debugging etc. Further reinforcing SWD as at least one interface into the part. Through that interface (SWD is ARM) you access the flash controller (has nothing whatsoever to do with arm it is chip specific) and through that you write your application binary that the part will run (the machine code and data that the processor uses, your application).
ISO is closely related to PC's with a BIOS/EFI which also means x86, and has nothing whatsoever to do with a microcontroller much less a non x86, non BIOS/EFI PC/Laptop. It is extremely unlikely that you can get enough software on a cortex-m0(+) based platform that if you had an interface to media that can hold it that you could parse it and extract anything useful, and then have resources left to load and execute any programs in ram. No way whatsoever in any part I have heard of that you could do this in ram such that you could extract something you could load to the flash on the part. Plus you have to get that program into the part before you can then later support ISO, if you could, which you can't.
The only remote way an ISO makes any sense at all or has any context is if on your PC you boot off of an ISO image and that ISO image for the PC (not the mcu) contains a development system. For example a pre-prepared Linux operating system distro with the tools from the vendor for this part so that you don't have to install the development system on your computer you can run it off a ramdisk using a live image on an ISO. That development system would not use ISO files but the proper file formats to develop binaries and load them to the board via SWD or some other chip/board specific interface.
Beyond that there is no further reason to talk about ISO's and microcontrollers.
Some chip vendors (not arm, the chip vendor) may also provide a factory bootloader or logic that supports for example a uart, maybe spi, maybe i2c, maybe usb interface that you can use chip (not arm) specific software to talk to software running on that chip (the bootloader) that can then write to the flash. You can also write your own bootloader if there are enough resources in the system. The (arm based) mcu world is moving away from these bootloaders, two of the three main companies that used to always have them have started to remove them or disable them as a default feature.
Other companies provide no other interface than SWD to program the part, SWD or nothing. Certainly in the cortex-m0+ market where every penny counts and the extra flash for a bootloader and extra chip real estate, etc add to the overall cost for a legacy feature that is becoming less important because developers can now easily obtain SWD interface modules for a few dollars. It is not like the old days where a JTAG board cost $2000. At this time all cortex-m parts support SWD, making it the most useful interface and reminding developers that having tools that can access that interface being worth the ($5, plus time to learn to use it) investment.
The tools used to write the flash dictate what file formats are supported, these days a raw binary image or an elf file format are the main two. The old days included file formats like Intel hex and Motorola s-record but it is only old timers like me that favor those file formats, even though an elf is trivial to parse, and a raw binary image even simpler, about four lines of code.
Some chip vendors do not provide enough information to roll your own, but most often they do. Arm long ago released the SWD interface information, so it is technically possible to roll your own and then support whatever file format you want. But you would have to distribute this tool along with the ISO file, so you would what use a second ISO file to distribute the tools to read the first one. Based on your question and comments you are a long long way from writing tools like these. Especially when working tools like openocd exist that support the main file formats (elf and raw binary) and can speak SWD into the current line of cortex-m cores.
Again if you are suggesting using an ISO to distribute tools along with your binary to be loaded and run on a PC that might make sense, but it is easier for the end user to simply download the tools from the chip vendor or tools vendor and then download the binary file from you, rather than put in the extra work to deal with an ISO.
I have Fedora installed on my PC and I have a Friendly ARM Mini2440 board. I have successfully installed Linux kernel and everything is working. Now I have some image processing program, which I want to run on the board without OS. The only process running on board should be my program. And in that program how can I access the on board camera to take image from, and serial port to send output to the PC.
You're talking about what is often called a bare-metal environment. Google can help you, for example here. In a bare-metal environment you have to have a good understanding of your hardware because you have to take care of a lot of things that the OS normally handles.
I've been working (off and on) on bare-metal support for my ELLCC cross development tool-chain. I have the ARM implementation pretty far along but there is still quite a bit of work to do. I have written about some of my experiences on my blog.
First off, you have to get your program started. You'll need to write some start-up code, usually in assembly, to handle the initialization of the processor as it comes out of reset (or is powered on). The start-up code then typically passes control to code written in C that ultimately directly or indirectly calls your main() function. Getting to main() is a huge step in your bare-metal adventure!
Next, you need to decide how to support your hardware's I/O devices which in your case include the camera and serial port. How much of the standard C (or C++) library does your image processing require? You might need to add some support for functions like printf() or malloc() that normally need some kind of OS support. A simple "hello world" would be a good thing to try next.
ELLCC has examples of various levels of ARM bare-metal in the examples directory. They range from a simple main() up to and including MMU and TCP/IP support. The source for all of it can be browsed here.
I started writing this before I left for work this morning and didn't have time to finish. Both dwelch and Clifford had good suggestions. A bootloader might make your job a lot simpler and documentation on your hardware is crucial.
First you must realise that without an OS, you are responsible for bringing the board up from reset including configuring the PLL and SDRAM, and also for the driver code for every device on the board you wish to use. To do that required adequate documentation of the board and it devices.
It is possible that you can use the existing bootloader to configure the core and SDRAM, but that may not meet your requirement for the only process running on the board should be your image processing program.
Additionally you will need some means of loading and bootstrapping; again the existing Linux bootstrapper may suit.
It is by no means straightforward and cannot really be described in detail here.
I was wondering if anyone knows an efficient way to program the FPGA(PL) for a Xilinx Zynq-7 series or related devices,from a host C program (not on the SoC, but from the host PC). Is there an Xilinx API I can use/include in my program. As the only way I can think of doing it at the moment is invoking command line programming via Impact.
Basically I want to put the SDK "Program FPGA" functionality in my host C program where the user selects a prebuilt .bit file (and .elf file if possible) to program the FPGA/(SoC). This is just for a test of concept, later I would like to put this dynamic configuration onto one of the ARM CPU's.
Many Thanks
Sam
At the very least you'll need an intermediate MPU/MCU that can read from USB, as at startup most FPGAs aren't capable of much at all. I'm guessing this'll make it hard to find a MPU/library pair to do so, because there are so many options, each of which would be pretty application-specific. You're better off starting with programming them off an ARM chip, since you'll need some CPU with the FPGA in any case.
This seems somewhat useful.
I am wondering how the OS is reading/writing to the hard drive.
I would like as an exercise to implement a simple filesystem with no directories that can read and write files.
Where do I start?
Will C/C++ do the trick or do I have to go with a more low level approach?
Is it too much for one person to handle?
Take a look at FUSE: http://fuse.sourceforge.net/
This will allow you to write a filesystem without having to actually write a device driver. From there, I'd start with a single file. Basically create a file that's (for example) 100MB in length, then write your routines to read and write from that file.
Once you're happy with the results, then you can look into writing a device driver, and making your driver run against a physical disk.
The nice thing is you can use almost any language with FUSE, not just C/C++.
I found it quite easy to understand a simple filesystem while using the fat filesystem on the avr microcontroller.
http://elm-chan.org/fsw/ff/00index_e.html
Take look at the code you will figure out how fat works.
For learning the ideas of a file system it's not really necessary to use a disk i think. Just create an array of 512 byte byte-arrays. Just imagine this a your Harddisk an start to experiment a bit.
Also you may want to hava a look at some of the standard OS textbooks like http://codex.cs.yale.edu/avi/os-book/OS8/os8c/index.html
The answer to your first question, is that besides Fuse as someone else told you, you can also use Dokan that does the same for Windows, and from there is just a question of doing Reads and Writes to a physical partition (http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx (read particularly the section on Physical Disks and Volumes)).
Of course that in Linux or Unix besides using something like Fuse you only have to issue, a read or write call to the wanted device in /dev/xxx (if you are root), and in these terms the Unices are more friendly or more insecure depending on your point of view.
From there try to implement a simple filesystem like Fat, or something more exoteric like an tar filesystem, or even some simple filesystem based on Unix concepts like UFS or Minux, or just something that only logs the calls that are made and their arguments to a log file (and this will help you understand, the calls that are made to the filesystem driver during the regular use of your computer).
Now your second question (that is much more simple to answer), yes C/C++ will do the trick, since they are the lingua franca of system development, also a lot of your example code will be in C/C++ so you will at least read C/C++ in your development.
Now for your third question, yes, this is doable by one person, for example the ext filesystem (widely known in Linux world by it's successors as ext2 or ext3) was made by a single developer Theodore Ts'o, so don't think that these things aren't doable by a single person.
Now the final notes, remember that a real filesystem interacts with a lot of other subsystems in a regular kernel, for example, if you have a laptop and hibernate it the filesystem has to flush all changes made to the open files, if you have a pagefile on the partition or even if the pagefile has it's own filesystem, that will affect your filesystem, particularly the block sizes, since they will tend to be equal or powers of the page block size, because it's easy to just place a block from the filesystem on memory that by coincidence is equal to the page size (because that's just one transfer).
And also, security, since you will want to control the users and what files they read/write and that usually means that before opening a file, you will have to know what user is logged on, and what permissions he has for that file. And obviously without filesystem, users can't run any program or interact with the machine. Modern filesystem layers, also interact with the network subsystem due to the fact that there are network and distributed filesystems.
So if you want to go and learn about doing kernel filesystems, those are some of the things you will have to worry about (besides knowing a VFS interface)
P.S.: If you want to make Unix permissions work on Windows, you can use something like what MS uses for NFS on the server versions of windows (http://support.microsoft.com/kb/262965)