How to call PXE API from protected mode (or C code)? - bootloader

I'm planning to write a bootloader for x86 and x64 architecture from where I wish to make UDP and TFTP calls using the PXE network stack built into the network card. I see that there's a PXE API that I can use. However, I want to write as little assembly as possible and would like to implement the UDP/TFTP communication in C (This will be a two-stage bootloader with only minimal assembly needed to transition away from BIOS and the main logic will reside in the second stage written in C). I presume that my C code can only run in protected mode whereas the PXE API can only be called in the real mode. So my question is, in order to call PXE will I have to temporarily transition back to real mode? I've heard that doing so is not without peril. Any help will greatly appreciated.

PXE API seems to have a dedicated entry point for 32-bit protected mode called EntryPointESP. Since I haven't tried it yet, I am not sure about all the details, but it should work. Consult PXE spec for more information.

Related

U-Boot application causes reset

This question might be too broad and may not be easily understandable until you see actual code or what is happening, but I thought I should give at least a try. I am porting U-boot for RISCV cpu on MAX10 FPGA in its DDR3 Memory. I have made all the necessary configurations for my specific board and processor as mentioned in the README of U-boot and it is successfully built as well.
But, currently I am unable to get into U-boot application for some reason. Whenever I prompt it to enter into address that I have specified in CONFIG_SYS_LOAD_ADDR which is 0x80000000, it resets and starts from address 0x00000000. I don't have any idea that why is this happening. Can someone expert with this stuff help me?
Whenever I prompt it to enter into address that I have specified in CONFIG_SYS_LOAD_ADDR which is 0x80000000, it resets and starts from address 0x00000000.
CONFIG_SYS_LOAD_ADDR is merely a default load address for various U-Boot commands (e.g. tftpboot).
The symbol that does need to be defined is CONFIG_STANDALONE_LOAD_ADDR, which is used as the linker address for standalone applications.
The U-Boot standalone applications are built as non-relocatable code.
Since your application was built with an unknown default link address, it is unlikely to properly execute at 0x80000000.
If you haven't already, you should also perform a memory test using U-Boot's memtest.

how to debug a pci device and linux driver

I am programming a pci device with verilog and also writing its driver,
I have probably inserted some bug in the hardware design and when i load the driver with insmod the kernel just gets stuck and doesnt respond. Now Im trying to figure out what's the last driver code line that makes my computer stuck. I have inserted printk in all relevant functions like probe and init but non of them get printed.
What other code is running when i use insmod before it gets to my init function? (I guess the kernel gets stuck over there)
printks are often not useful debugging such a problem. They are buffered sufficiently that you won't see them in time if the system hangs shortly after printk is called.
It is far more productive to selectively comment out sections of your driver and by process of elimination determine which line is the (first) problem.
Begin by commenting out the entire module's init section leaving only return 0;. Build it and load it. Does it hang? Reboot system, reenable the next few lines (class_create()?) and repeat.
From what you are telling, it is looks like that Linux scheduler is deadlocking by your driver. That's mean that interrupts from the system timer doesn't arrive or have a chance to be handled by kernel. There are two possible reasons:
You hang somewhere in your driver interrupt handler (handler starts its work but never finish it).
Your device creates interrupts storm (Device generates interrupts too frequently as a result your system do the only job -- handling of your device interrupts).
You explicitly disable all interrupts in your driver but doesn't reenable them.
In all other cases system will either crash, either oops or panic with all appropriate outputs or tolerate potential misbehavior of your device.
I guess that printk won't work for such extreme scenario as hang in kernel mode. It is quite heavy weight and due to this unreliable diagnostic tool for scenarios like your.
This trick works only in simpler environments like bootloaders or more simple kernels where system runs in default low-end video mode and there is no need to sync access to the video memory. In such systems tracing via debugging output to the display via direct writing to the video memory can be great and in many times the only tool that can be used for debugging purposes. Linux is not the case.
What techniques can be recommended from the software debugging point of view:
Try to review you driver code devoting special attention to interrupt handler and places where you disable/enable interrupts for synchronization.
Commenting out of all driver logic with gradual uncommenting can help a lot with localization of the issue.
You can try to use remote kernel debugging of your driver. I advice to try to use virtual machine for that purposes, but I'm not aware about do they allow to pass the PCI device in the virtual machine.
You can try the trick with in-memory tracing. The idea is to preallocate the memory chunk with well known virtual and physical addresses and zeroes it. Then modify your driver to write the trace data in this chunk using its virtual address. (For example, assign an unique integer value to each event that you want to trace and write '1' into the appropriate index of bytes array in the preallocated memory cell). Then when your system will hang you can simply force full memory dump generation and then analyze the memory layout packed in the dump using physical address of the memory chunk with traces. I had used this technique with VmWare Workstation VM on Windows. When the system had hanged I just pause a VM instance and looked to the appropriate .vmem file that contains raw memory latout of the physical memory of the VM instance. Not sure that this trick will work easy or even will work at all on Linux, but I would try it.
Finally, you can try to trace the messages on the PCI bus, but I'm not an expert in this field and not sure do it can help in your case or not.
In general kernel debugging is a quite tricky task, where a lot of tricks in use and all they works only for a specific set of cases. :(
I would put a logic analyzer on the bus lines (on FPGA you could use chipscope or similar). You'll then be able to tell which access is in cause (and fix the hardware). It will be useful anyway in order to debug or analyze future issues.
Another way would be to use the kernel crash dump utility which saved me some headaches in the past. But depending your Linux distribution requires installing (available by default in RH). See http://people.redhat.com/anderson/crash_whitepaper/
There isn't really anything that is run before your init. Bus enumeration is done at boot, if that goes by without a hitch the earliest cause for freezing should be something in your driver init AFAIK.
You should be able to see printks as they are printed, they aren't buffered and should not get lost. That's applicable only in situations where you can directly see kernel output, such as on the text console or over a serial line. If there is some other application in the way, like displaying the kernel logs in a terminal in X11 or over ssh, it may not have a chance to read and display the logs before the computer freezes.
If for some other reasons the printks still do not work for you, you can instead have your init function return early. Just test and move the return to later in the init until you find the point where it crashes.
It's hard to say what is causing your freezes, but interrupts is one of those things I would look at first. Make sure the device really doesn't signal interrupts until the driver enables them (that includes clearing interrupt enables on system reset) and enable them in the driver only after all handlers are registered (also, clear interrupt status before enabling interrupts).
Second thing to look at would be bus master transfers, same thing applies: Make sure the device doesn't do anything until it's asked to and let the driver make sure that no busmaster transfers are active before enabling busmastering at the device level.
The fact that the kernel gets stuck as soon as you install your driver module makes me wonder if any other driver (built in to kernel?) is already driving the device. I made this mistake once which is why i am asking. I'd look for the string "kernel driver in use" in the output of 'lspci' before installing the module. In any case, your printk's should be visible in dmesg output.
in addition to Claudio's suggestion, couple more debug ideas:
1. try kgdb (https://www.kernel.org/doc/htmldocs/kgdb/EnableKGDB.html)
2. use JTAG interfaces to connect to debug tools (these i think vary between devices, vendors so you'll have to figure out which debug tools you need to the particular hardware)

How to hook syscall table at runtime on PPC Linux?

Subject: PPC Assembly Language - Linux Loadble Kernel Module
Detail: How access local TOC area (r2) when called from kernel in syscall table hook?
I have written a loadable kernel module for Linux that uses syscall table hooking to intercept system calls and log information about them before passing the call on to the original handler. This is part of a security product. My module runs well and is in production code running on a large variety of Linux kernel versions and distributions with both 32 and 64 bit kernels all running on x86 hardware.
I am trying to port this code to run on Linux for PPC processors and ran into a few problems. Using the Linux kernel source, it is easy enough to see how the system call table is implemented differently on PPC. I can replace entries in the table with function addresses from my own compiled handlers, no problem.
But, here's the issue I'm having trouble with. The PPC ABI uses this thing called a Table Of Contents (TOC) address which is stored in the CPU's R2 register and expects to address a module's global and local data by using an offset from the address (TOC address) contained in that register. This works fine in normal cases where a function call is made because the compiler knows to load the module's TOC address into the register before making the call (or its already there becasue normally your functions are called by your own code).
However, when I place the address of my own function (from my loaded kernel module at runtime) into the system call table, the kernel calls my handler with an R2 value that is not the one my compiled C code expects, so my code gets control without being able to access its data.
Does anybody know of any example code out there showing how to handle this situation? I cannot recompile the kernel. This should be a straightforward case of runtime syscall table hooking, but I have yet to figure it out, or find any examples specific to PPC.
Ideas include:
Hand coding an assembly language stub that saves the R2 value, loads the register with my local TOC address, executes my code, then restores the old value before calling the original handler. I don't have the depth of PPC assembly experience to do this, nor am I sure it would work.
Some magic gcc option that will generate my code without using TOC. There is a documented gcc option "-mno-toc" that doesn't work on my PPC6 Linux. It looks like it may only be an option for system V.4 and embedded PowerPC.
Any help is greatly appreciated !
Thanks!
Linux has a generic syscall audit infrastructure which works on powerpc and you can access from user space. Have you considered using that rather than writing a kernel module?
You need a stub to load r2. There are examples in the kernel source.

How to write to I/O ports in Windows XP? (Delphi7)

I am trying to write to ports 0x60 and 0x64, with no luck.
Delphi code:
procedure PortOut(IOport: WORD; Value: BYTE); assembler; register;
asm
XCHG DX,AX
OUT DX,AL
end;
Upon calling PortOut, I get an EPrivilege Privileged instruction exception, because IN and OUT may only execute as Ring0.
I would like to know how I can get Ring0 privileges my an application or how I could write to ports 0x60 and 0x64 using some existing external library.
Have a look at the IO.DLL from Geek Hideout.
IO.DLL allows seamless port I/O
operations for Windows
95/98/NT/2000/XP using the same
library.
Here is an example: Parallel Port I/O Using Delphi V 6.0
The correct way to handle this situations is to write a Windows driver, but it can't be done in Delphi for lack of support. It requires the DDK and a C compiler. The other solutions presented here works, but be aware that usually the give access to any I/O port, not only those your application requires. And that could be a security issue - if the x86 architecture lets the system programmer to define the IOPL (I/O privilege level) and most systems set it a ring 0, there's a reason.
General access I/O ports drivers are useful for tests and maybe prototyping or as stopgap measures, but I will be very careful to deploy them, especially if the system in not under strict control. If you need that kind of access, you definitely need to understand how the Windows kernel and its drivers works, and why - and implement your own driver.
Most of the time Windows in not unsecure per se - it is running to many unsecure software with the wrong privileges that make it so.
Inpout32.dll for Windows 98/2000/NT/XP (binaries and source code)
Inpoutx64.dll for WIN XP 64 bit (binaries and source code)
Delphi: Accessing Port Hardware and how to use InpOut32.dll
Of course that might cause trouble for devices that are controlled by a driver. Stuff like IO.DLL is mostly meant to interface cards for which no Windows drivers exist, or where the windows driver is dormant until activated.
And since port 60h is the keyboard controller, and the keyboardi is usually in use, it might cause problems.
If you are not interfacing ancient hardware, but just trying to port dos (TP) code, I urgently advise you to rewrite the said code based on normal Windows APIs.
Jeez,
It has been a long time for me. I just launched my DPro 2006 to look at the VCL on this and it bombed. (Guess that is what I get for not doing any Delphi code in the the last couple of years on this machine... and keeping patching up to date, plus installing/uninstalling a jillion other paid and FOSS packages on the box....)
But it would seem to me that if you grabbed the header files for the Windows Driver Framework, or check out Project JEDI's site, you might find something to put together a Miniport driver or such.
Just my $0.02 worth
/s/ BezantSoft

Modifying the MBR of Windows

I need to modify the MBR of Windows, and I would really like to do this from Windows.
Here are my questions. I know that I can get a handle on a physical device with a call to CreateFile. Will the MBR always be on \\.\PHYSICALDRIVE0? Also, I'm still learning the Windows API to read directly from the disk. Is readabsolutesectors and writeabsolutesectdors the two functions I'm going to need to use to read/write to the disk sectors which contain the MBR?
Edit from from what I've learned on my own.
The MBR will not always be on \\.\PHYSICALDRIVE0. Also, you can write to the bootsector (at least as Administrator on XP) by call CreateFile with the device name of the drive that contains the MBR. Also, you can write to this drive by simply calling WriteFile and passing the handle of the device created by calling CreateFile.
Edit to address Joel Coehoorn.
I need to edit the MBR because I'm working on a project that needs to modify hardware registers after POST in BIOS, but before Windows will be allowed to boot. Our plan is to make these changes by modifying the bootloader to execute our code before Windows boots up.
Edit for Cd-MaN.
Thanks for the info. There isn't anything in your answer, though, that I didn't know and your answer doesn't address my question. The registry in particular absolutely will not do what we need for multiple reasons. The big reason being that Windows is the highest layer among multiple software layers that will be running with our product. These changes need to occur even before the lower levels run, and so the registry won't work.
P.S. for Cd-MaN.
As I understand it, the information you give isn't quite correct. For Vista, I think you can write to a volume if the sectors being written to are boot sectors. See http://support.microsoft.com/kb/942448
Once the OS is started the MBR is typically protected for virus reasons - this is one of the oldest virus tricks in the books - goes back to passing viruses from floppy to floppy.
Even if it wasn't restricted, you have to write low level code - it isn't part of the file system, but exists on a specific location on the hard drive.
Due to that, you pretty much are restricted to writing low level (most programs implement this in assembly) or C code targeting 16 bit DOS.
Most of these programs use the BIOS interface (13h, I believe) to access the sectors of the disk directly. You can access these in C using some inline assembly, or compiler provided interfaces. You will generally not get access to BIOS without the cooperation of the OS, though, so your program, again, will be restricted to DOS. If you can access these you're almost home free - the nice thing about BIOS is you don't have to worry about what type of HD is in the system - even RAID cards often insert themselves into the BIOS routines so they can be accessed without knowing where in memory the ATA or SATA controller is, and executing commands on that low level.
If you absolutely must access it within an OS, though, you pretty much have to write a device driver to access the BIOS or the memory space where the HD controllers exist. I wouldn't recommend it, though, as this is very tricky to deal with - modern computers put the HD controllers in different spots in memory, with different IRQs, and each chipset has become a little more esoteric because they can provide a minimum interface to bios for bootup, and then a specific driver for Windows. They skip all the other interface niceties that would be considered compatible with other controllers because it's more expensive to be compatible.
You may find that at the driver level inside windows you'll have methods for accessing the drive sectors directly (or pseudo directly), but again, they are likely very well protected due to the aforementioned virus issues.
Good luck!
Modifying the bootloader is bad, bad idea. Here are just a few of the possible gotcha's:
it will potentially kill full disk encryption products (Truecrypt, PGP, Vista's BitLocker, etc)
it will potentially trip up AV products (scaring users)
it will potentially kill complicated booting scenarios (chained boot loaders, etc)
it will kill off the chain of trust when using the TPM module (because it checks the MBR for change before executing it)
direct disk access is not allowed starting from Vista (only using drivers)
Alternatives (like modifying the hardware register during the Windows bootup via a driver which is set to load at boot time or after Windows has booted) should really be considered. If the modification is as simple as writing to a port, ie:
OUT AX, BL
then drivers exists for all versions of Window which can do this (reading/writing a value from/to a certain port) which can be called from user mode.
Maybe a PXE boot scenario could help you? Simply boot on your crafted PXE image which modify the hardware registers you need to modify, and then return the control to the Master Boot Record or to the active partition's boot record.
This way you don't have to modify the boot records.

Resources