Hi, folks
I'm trying to boot our VxWorks based application from using LinuxBios. On our board we have 512K Flash and 16M CF. VxWorks image is several megs in size, so I put it on CF.
I use linuxbios and VxWorks boot loader, which is essentially a stripped down VxWorks kernel with 32-byte a.out header removed, to create a flash romimage. The idea is to let linuxbios load VxWorks boot loader into memory and let it load VxWorks from CF.
Essentially, I've simply mimicked the romimage creation steps, just instead of linux kernel I use VxWorks bootloader.
I can see that bootloader is successfully uncompressed into RAM, but nothing happens after I jump to it's code. According to VxWorks docs, bootloader should be copied to address 0x8000. I've tried to modify do_inflate.c and linuxbiosmain.c to load and jump to this address, but gunzip returned error.
Now the question. Do you think this approach can work, or I am I doing something entirely wrong ?
Should I convert a.out image of VxWorks bootloader into binary image.
Can I modify linuxbios code to allow VxWorks boot loader to be loaded at 0x8000 ?
Any other ideas will be much appreciated.
TIA.
Felix.
On Wed, 5 Feb 2003, Felix Radensky wrote:
Now the question. Do you think this approach can work, or I am I doing something entirely wrong ?
it can work. Are you sure you have RAM turned on correctly? Is there some way you can use mkelfImage to build a better image?
Can I modify linuxbios code to allow VxWorks boot loader to be loaded at 0x8000 ?
sure, but I recommend you cut over to and elfImage.
ron
On Wed, 2003-02-05 at 10:37, Felix Radensky wrote:
Hi, folks
I'm trying to boot our VxWorks based application from using LinuxBios. On our board we have 512K Flash and 16M CF. VxWorks image is several megs in size, so I put it on CF.
I use linuxbios and VxWorks boot loader, which is essentially a stripped down VxWorks kernel with 32-byte a.out header removed, to create a flash romimage. The idea is to let linuxbios load VxWorks boot loader into memory and let it load VxWorks from CF.
Essentially, I've simply mimicked the romimage creation steps, just instead of linux kernel I use VxWorks bootloader.
I can see that bootloader is successfully uncompressed into RAM, but nothing happens after I jump to it's code. According to VxWorks docs, bootloader should be copied to address 0x8000. I've tried to modify do_inflate.c and linuxbiosmain.c to load and jump to this address, but gunzip returned error.
Now the question. Do you think this approach can work, or I am I doing something entirely wrong ?
Should I convert a.out image of VxWorks bootloader into binary image.
Can I modify linuxbios code to allow VxWorks boot loader to be loaded at 0x8000 ?
Any other ideas will be much appreciated.
I did this experiment once, except I executed the full-up vxWorks kernel instead of the bootloader. I believe that in addition to jumping to 8000h physical, I needed to switch to real mode, and that the segment:offset needed to be 800:0.
//copy 1 flash page to vxworks start address memcpy((void *)0x8000, (void *)0xfffe0000, 0x20000);
//patch the code in flashOSBootasm() /* Code to be run at 0x800:0 expects real mode, so flashOSBootasm() performs a 2 part mode switch. The 1st part is loading all segment regs with 16-bit segments, including jumping to a 16-bit code segment in protected mode. The GDT in intel_start32.S has a selector 0x28 with base 0xf0000 & limit 0xffff. 0x28 therefore maps to the BIOS, but offsets are exactly 0xf0000 lower than in a flat segment. There is a jmp 28:0000 instruction in flashOSBootasm(), followed immediately by the flat32 offset of the actual code to be jumped to. So right here, we get a pointer to the code to be jumped to, read that address embedded in the 4 bytes preceding the code, and copy the low 2 bytes to the jump instruction in the x bytes preceding _that_. You really have to trace through the code with an ICE to see what really happens. The 2nd part of the mode switch, after the cr0 reg is changed, is the jump to a real-mode segment offset address. */
pc = (unsigned char *)offset_patch_address; //553 pc2 = pc; pc -= (0x553 - 0x549); pc2 -= (0x553 - 0x54f);
//unprotect the bios in shadow ram c = csreadc(0x59); cswritec(0x59, c | 0x20); pc[0] = pc2[0]; pc[1] = pc2[1]; __asm__("wbinvd"); //do not write protect, we lose the changes! What the hell! // cswritec(0x59, c);
flashOSBootasm(); }
Unfortunately I can't find the asm code. Still looking.
Asm part of jump from Linuxbios to vxWorks
Hi, Christopher
Thanks a lot for the code. I really appreciate it ! Did you modify the linuxbios itself to allow VxWorks to be loaded at 8000h. I guess I have to modify ldscript.ld but i don't know how.
Thanks a lot.
Felix.
Christopher Stutts wrote:
Asm part of jump from Linuxbios to vxWorks
// // cpmasm.S // // Performs real-mode switch and then jump to code copied to flash at 0x800:0. // (VxWorks startup code expects a 0 offset, so 0:0x8000 is verboten.) // Mode switch is two part: loading all seg registers with 16-bit segments, then // jumping to realmode segment. GDT in intel_start32.S contains a 16-bit data segment // 0x30 & a 16-bit code segment 0x28. 0x28:0 = 0xf0000 physical. The jump to // 0x28:offset_patch_address requires a far jump with a 16-bit offset, which the assembler // doesn't do. The offset there fore is patched before we get executed by some C code.
.text // .code32
.global flashOSBootasm flashOSBootasm:
//Load all data segment regs with a 16-bit segment mov $0x30,%ax mov %ax,%ds mov %ax,%es mov %ax,%fs mov %ax,%gs mov %ax,%ss
//Jump to a 16-bit code segment ljmp $0x28,$0x00000000
.global offset_patch_address .long offset_patch_address offset_patch_address:
movl %cr0, %eax //mov eax,cr0 and $0xfffffffe,%eax //and eax,0ffffffFEh movl %eax,%cr0 //Switch back to real-mode without resetting
.global PROTECTION_DISABLED PROTECTION_DISABLED:
.code16
//Load all data segments regs with 0 until realmode code sets them mov $0,%ax nop nop mov %ax,%ds mov %ax,%es mov %ax,%fs mov %ax,%ss mov %ax,%gs
//opcode for real-mode jump to 800:0 .byte 0xea,0,0,0,0x8 .code32
On Wed, 2003-02-05 at 12:16, Felix Radensky wrote:
Hi, Christopher
Thanks a lot for the code. I really appreciate it ! Did you modify the linuxbios itself to allow VxWorks to be loaded at 8000h. I guess I have to modify ldscript.ld but i don't know how.
Thanks a lot.
Felix.
Two years ago(?), working from an old tarball on a 430TX-based board, I threw the quoted C code in where the jump to the linux kernel normally goes, and apparently I modified the GDT as well. The experiment convinced us to go this route for our PIII BX board running a different RTOS instead of buying a BIOS solely for its SDRAM init, pci enumeration, & disk boot capabilities.
If there is a cleaner switch to real mode available now, use it. (You can see that I was patching code in ram in order to jump to a 16-bit protected mode segment, and that the chipset wasn't entirely cooperating.) You might also look to see if there is a protected mode entry point to your vxWorks code. I don't know if that is feasible or not. We haven't done vxWorks for 2 years, and only a couple printed manuals were saved from the Great Purge.
if you folks figure out vxworks from linuxbios and write it up I can put it in the FAQ
ron
"Ronald G. Minnich" rminnich@lanl.gov writes:
if you folks figure out vxworks from linuxbios and write it up I can put it in the FAQ
For this and possibly for the plan9 support I will except patches to mkelfImage. As of version 2.0 it has an infrastructure that allows for adding code for various targets.
And the code is all in C so it is fast.
ftp://ftp.lnxi.com/pub/src/mkelfImage/
Basically to load vxworks at 0x8000 you just need an ELF header that says load me here. And probably a bit of adapter code that switches from 32bit protected mode to 64bit protected mode.
Eric
Eric W. Biederman wrote:
Basically to load vxworks at 0x8000 you just need an ELF header that says load me here.
Is this going to work even if LinuxBios itself uses memory at 0x8000 ? In my current setup (without USE_ELF_BOOT) decompression of VxWorks boot loader fails at 0x8000 but succedes at 0x100000.
Can elfboot handle compressed images ?
I'll gladly provide a patch for mkelfimage, but I'll need some basic guidance, as I'm not familiar with internals of ELF format. Eric, can you please recommend some docs and code to look at, so I can get familiar with the format.
And probably a bit of adapter code that switches from 32bit protected mode to 64bit protected mode.
This sounds a bit cryptic to me. Can you please elaborate on that.
Thanks.
Felix.
Felix Radensky felix@allot.com writes:
Eric W. Biederman wrote:
Basically to load vxworks at 0x8000 you just need an ELF header that says load me here.
Is this going to work even if LinuxBios itself uses memory at 0x8000 ?
Essentially yes, it will either work or refuse to load. I do not think the LinuxBIOS tables extend that far up into memory which is the only case it would refuse to load the image for. The LinuxBIOS code itself is copied to the top of memory before the image is loaded, so it does not get in the way.
In my current setup (without USE_ELF_BOOT) decompression of VxWorks boot loader fails at 0x8000 but succedes at 0x100000.
Can elfboot handle compressed images ?
Yes, you put a self decompresser in the image.
I'll gladly provide a patch for mkelfimage, but I'll need some basic guidance, as I'm not familiar with internals of ELF format. Eric, can you please recommend some docs and code to look at, so I can get familiar with the format.
First there is nothing special about mkelfImage. It is just a repository for the code to convert various types of images into a format the elf loader can handle. For each different image type there is a whole different set of code.
The easy reference to come by is /usr/include/elf.h
Basically there is an ELF header Elf32_Ehdr/Elf64_Ehdr followed by a program header. Elf32_Phdr/Elf64_Phdr. Followed by the data to load into memory.
The Ehdr reports what kind of elf image you have 32bit or 64bit, little endian or big endian, which architecture the code is for where the entry point is, and how many phdrs you have.
Each phdr describes a chunk of the image, and specifies where in memory to load it.
The ELF structures are a little verbose, but not prohibitively so, and allow a clean way of specifying what to load and where. The elf loader is simply a mechanism where the LinuxBIOS can provide a fixed interface, and the rest of the OS's can come to that one interface with just a little bit of glue code.
And probably a bit of adapter code that switches from 32bit protected mode to 64bit protected mode.
This sounds a bit cryptic to me. Can you please elaborate on that.
Don't worry about it, I am working on Hammer stuff at the moment, and parts of my brainstorming on how to handle the issues raised by a 64bit port keep spilling out...
Eric