How could I get input inside my kernel inside a freestanding environment? - c

I am making an operating system in assembly and I just integrated c. I want to get input but you can include stdio.h inside a freestanding environment. How would I go about getting user input inside a freestanding environment

A simple approach would be to read your CPU's architecture manual to check for the entry in the IDT corresponding to the keyboard (9th entry if I recall correctly in x86).
And add a pointer to the function handling your keyboard input.
Usually what you want in that function is to store each input in a buffer accessible to other kernel functions. In order to "speak" to the device, you will have to follow a protocol. Usually, for simple examples it is PS/2. You'll find extensive documentation over https://wiki.osdev.org/PS/2_Keyboard.
Also, you can check this simple example here: https://github.com/TretornESP/StolenOS/blob/main/keyboard.asm
Basically what install_handler does is to alter the IDT to point the 9th entry to the function keyboardHandler.
keyboardHandler searches for a specific code in the device's memory. If found, uses a keyboard map file to translate ps/2 codes to ASCII characters and stores them in a buffer until the return key is pressed.
This approach is as simple as it gets without polling.

Related

How does main force arguments it takes (from command line) to become strings

Im beginner who encounters concept of command line arguments for first time and it really confuses me.
When we write at command line after the programs name anything it gets converted to a string.
But how is main able to do that? Does it interact with system itself and tells system (instructs system itself) everything written here in command line is now argument to my program? Can it do that because system itself is written in c too so it can interact with it outside of program it itself is part of?
Also is there equivalent of that in gui?
And i understand it can take ints and convert them to strings. But what if we wanted to type in other data type as argument in command line.Like boolean for example, is it error like data provided not matching argument required by function?
In typical implementations, command-line arguments are parsed by the command-line shell and then passed to the program being executed. In Unix systems, a new program is executed by calling a system routine in the “exec” family, and the arguments are passed to those routines as a list of pointers to character strings (in one form or another).
In any hosted C implementation that conforms to the C standard, the program arguments are prepared before main is called. main does not interact with the system to do that; it is done before main is called.
But what if we wanted to type in other data type as argument in command line.
You cannot type any other data type. On your keyboard, you can only press keys. There is no key on your keyboard that creates a boolean value or even an int value like 3. When you press a key1, a signal is sent to the computer, with information about which key you pressed. Software on the computer interprets the pressed key. Roughly, in a “normal” text-input terminal mode, if the pressed key represents some character, like “A” or “3” or “+”, that character will be added to a buffer that is being used to collect user input. When the user presses Return/Enter or does certain other actions, that buffer of characters will be sent to the current program attached to the terminal. (There may be other terminal modes available in which keypresses are processed differently, such as a sent directly to a program routine, which might interpret them as commands in a game being played.)
Footnote
1 The specifics of this may depend on the key and the hardware. Pressing a Shift key might not send a signal to the computer; the keyboard might merely use that to affect the signals it sends when you press another key on conjunction with Shift.
The system passes everything as a string, because it cannot know what kind of datatypes your program can handle or how it stores them. It does not know that your program is written in C. For all it knows, it could be Python, Java, JavaScript, Rust etc. and those all have and store different kinds of datatypes slightly differently, so the system cannot assume anything. Therefore programs just receive everything as a string and leave it to the programmer to convert it to the right datatypes if they so wish.
Does it [main()] interact with system itself and tells system (instructs system itself) everything written here in command line is now argument to my program?
The command line is always a sequence of characters, and the operating system cannot know what arguments actually mean or in which programming language a program was written in. So the program receives the command line as a sequence of characters.
Any program written in a high-level programming language (meaning, not assembly) has some kind of start-up code. This code makes sure that the first executed user code gets the environment prepared as specified for the programming language.
For example, the C standard promises that any static variables is initialized, implicitly or explicitly. And concerning your question, the C standard promises that the command line is processed in a way that main() receives the number of arguments, an array of pointers to them, and that all of the arguments are zero-terminated.
Such a start-up code is commonly written in assembly language, because only this is able to access any necessary resource like CPU registers or special functions of the operating system.
Can it do that because system itself is written in c too so it can interact with it outside of program it itself is part of?
The operating system can be written in any programming language. It "just" needs to fulfill the specified requirements, commonly called API, application programming interface.
Also is there equivalent of that in gui?
It depends on what you mean by "GUI".
If you prepare some preferences of, let's say, your IDE, you often see GUI dialogs offering text fields for command lines.
Additionally, many desktops allow to drag-and-drop files on a program's executable. The filenames (with full path) are given as arguments in the command line to the program. Astonishingly, this also works on Windows.
And i understand it can take ints and convert them to strings. But what if we wanted to type in other data type as argument in command line.Like boolean for example, is it error like data provided not matching argument required by function?
No command line takes integers. Such arguments are just sequences of digits and included in the command line as any other sequence of characters.
Each character is encoded in an integer, though. This encoding depends, well, on the encoding like UTF-8 or (extended) ASCII.
If your program needs to interpret specific arguments as integers, booleans, any type you want, it has to do the conversion itself. Fortunately, most programming languages provide libraries with lots of functions that help us doing so.

Use printf in embedded c

I work on the Aurix microcontroller on eclipse
i need to display unsigned char values on the console,
I did like that
printf ("% hhx", tab [j]);
but I had this error:
error: AppKit_TC277TFT_TimeDemo.elf section `.inttab' will not fit in
region `PMI_PSPR'
error: region `PMI_PSPR' overflowed by 16788 bytes
Is there anyone who could help me
Searching for PMI_PSPR Aurix in a well-known search service brings up this forum post.
Apparently you are linking your code to run from RAM. Change the linker settings to link it to flash, and run from there.
First try to isolate what is the cause. Two thoughts are:
Check if the stdout stream works.
Check if a memory issue (as the error suggests).
1. stdout check:
Try using the stdout stream without using printf formatter. The formatter is bloated as people suggest and generally not a good idea on embedded systems. Also have you setup where the stdout stream goes (is it mapped to some UART code, normally on embedded systems you need to write or configure this)? Test by using putch('.'), putchar('.') or even puts("Hello").
2. memory check:
Try building the code that uses sprintf() by itself without stdout. If that doesn't build either then it is likely the formatter. Some embedded compilers allow configuring the formatter library as smaller options to get around this issue (doesn't support the full implementation).
Use printf in embedded c
One way is to use UART communication.
Convert numeric value to printable ascii form and send to UART so that one may see on console.
For simple applications you may consider storing printable characters to some array buffer and at the end of activity print the array buffer to UART

Generating load time serial number for PCB application

I am trying to generate an incrementing value at load time to be used to "serialize" a PCB with a unique code value. Not an expert in ld or preprocessor commands, so looking for some help.
The value will be used in a unique ID for each board that the code is loaded on and will also be used as a counter for boards in the field.
I have no preconceived idea of how I might accomplish this, so any workable answer to get me started, including a pre-preprocessor macro is fine. In my olden days, I recollect adding a couple lines to the linker file that would accomplish this, but I have been unable to resurrect that information anywhere (including my brain's memory cells).
The simpler the answer, the better.
My solution to the problem was remarkably simple.
The binary contained
const char *serial = "XY-00000";
I then wrote a short program that boiled down to:
char uniqueserial [8];
/* Generate serial - this was an SQL call to the manufacturing DB */
char *array;
/* Read binary into array */
memcpy(memmem(array, "XY-00000",8), uniqueserial,8);
/* Write array to temp bin file for flashing */
Depends on the serial template string being unique in the binary. Use strings command to check. I disable crc protected object files due to taste. I like my embedded binaries being exact memory dumps.
The linker is not the right place for two reasons:
the executable can be loaded with the same id in several devices, making your approach void.
You should have to link the executable for each device you are programming, which poses an spent of cpu resources.
The best place is to patch the executable at loading time with the serial number.
Select a data patern as token to initialize your variable with the device id (a pattern difficult to happen elsewhere in your program binary) and initialize your serial number variable to that data pattern (better if you do it statically initializing an array variable or something similar)
Make a program to be executed on each download to device that search for the pattern in the executable file, before loading the binary program into the device and writes the correct value to be programmed into the device (beware that you are patching a binary, so you cannot think on variable lenght strings or the like, that can trash all the work made by the linker)
Once patched the binary executable, you can download it to the device.
Another solution is to reserve a fixed area in your linker script for all this kind of information. Then, put all your device information variables there. Then get the exact positions in rom for the individual variables and include the proper data in the loaded image. In this case, the linker is your friend, reserving some fixed segment in your device's rom allocated for storing the device's individual data (you can put there mac addresses, serial numbers, default configuration, etc.)

How to implement previous-command-scroll in a standalone shell program?

For a class project we have to implement a basic Linux shell. As it stands now I have everything working to fully implement basic functionality except for the "UP" key previous command scrolling feature.
How might something like this be implemented? I realize it may be as simple as retaining an array of char* to the input strings, but how do we capture "UP" key button presses?
Once we have the above implemented, how can you write to stdout without making it permanent? That is, when you press "UP" again then it erases what was previously written with another command.
A practical way to implement the up key would be to use GNU readline library (and its history sub-library). BTW, some shells actually do use GNU readline (it is under GPL license). And you'll get line edition also. And you could implement completion with the tab key, etc.
There are other ways, like using ncurses or termcap etc... Or emitting ANSI escape codes on a raw terminal. See also the tty demystified & termios(3)...
BTW, most Linux shells are free software, so you could study their source code.
If you are using non-buffered character-by-character input directly from STDIN (which means, among other things, control characters such as CTRL+C are not handled automatically), then you will be reading byte-by-byte. Arrow keys, unlike ASCII symbols, put multiple bytes on STDIN because they are excape sequences. These bytes differ from system to system. The easiest way to determine the escape sequence on your system is to execute the cat command with no arguments, then hit the arrow keys. Something like ^[[A will be displayed, you will need to convert that sequence from ASCII to hex bytes.
Once you've done that, you can read the bytes one at a time with get_char(), just like you're probably already doing in your input function anyway.

C - Read Directly From the Keyboard Buffer

This is a question in the C programming language.
How do I directly read the data in the keyboard buffer?
I want to directly access the data and store it in a variable. Of what data type should the variable be?
I need it for an operating system our institute is currently developing. It's called ICS-OS and I am not quite sure about the specifics. It runs on x86, 32-bit machines (we run it on QEMU in a Linux box). Here is the link for the Google Code http://code.google.com/p/ics-os/. I hope that's sufficient enough information.
The operating system does not support the conio.h library so kbhit is not an option.
This is really platform dependent.
If this is for Windows, the most direct access to a "keyboard buffer" is using WM_INPUT and GetRawInputData. See Using raw input with example for both keyboard and mouse.
Another DOS / Windows specific way are conio.h functions getch() / kbhit().
Portable library is called Curses and has ports for both Linux and Windows.
However, as you are targeting quite specific OS, you need to check the docs for that OS.
The most direct platform independent way is getchar / scanf / anything which reads from stdin, but stdin is line buffered, therefore you will get no data until enter is pressed. You may be able to change the buffering settings, but again, this is platform dependent and may be not possible on some platform. See a related discussion of setbuf(stdin,NULL).
Have you tried looking at the source code of the linux kernel for the keyboard driver?
Take a look at /drivers/input/keyboard/xtkbd.* for a simple XT keyboard driver.
Also, here's an article which briefly explains how it's done.
if you want to directly read data from keyboard buffer then you can user getchar or getc!
This is read from keyboard buffer
scanf("%d",&myvariable);
but you have to use
"%d" for int ,"%f" for float ,%e for double ,"%c" for char , "%s" for strings to identifing type which has to match type of your variable.

Resources