Ricardo Kazumi Ashikawa <ashikawa@dixtal.com.br> wrote:
First of all, there won’t be a DOS version released, but there may be a
windows version released at some point in the future, as part of a
Windows-based cross development system. For now, you’ll need to use the
QNX version.
Fine! That is exactly what I need! I have QNX SDK for Windows.
For getting your IPL to the board, I assume you have some sort of
DOS utility which allows you to copy images to the paged flash, and that
this is what you used to copy the IPL BIOS extension to the flash, and
perhaps the
boot image you generated with mkifs.
As for booting with the IPL, the routines (image_scan_ext() and
image_setup_ext())
expect linear memory, so you’ll need to do some extra work to boot from
paged flash. I’d recommend leaving the IPL routines alone, and writing an
extra routine which copies the boot image from paged flash to DRAM first,
and
then calling the normal IPL functions.
Alright. So, I just tried to code image_download_my_flash in IPL, but I have
some
doubts.
The c main in ipl runs in real-mode, right? I could not access flash memory.
When I am running a program in protected mode, I just run mmap to 0xD8000
and it works fine. However, when I tried to access 0xD8000 in
image_download_my_flash, I could not access flash memory correctly. It
always returns 00 for all data. Is this approach correct? If not so, which
address should be the correct one?
Correct, we’re still running in real mode here. This means that you don’t
need to use threadctl or mmap calls to map memory and I/O - the kernel
hasn’t loaded yet, and you can still talk directly to the hardware. It
also means that you have to convert physical addresses to segment:offset
addresses to access memory. The following code may help. It was written
a couple of assembler versions ago, so the inline asm isn’t guaranteed
to still work, but it should be a start:
asm(".code16gcc");
#include “ipl.h”
#include <x86/inout.h>
int main(){
unsigned long image = 0;
print_string(“QNX 6 paged flash loader\n”);
print_string(“press any key to boot from disk\n”);
if (get_timed_char (2000) != -1) {
print_string (“stopped\n”);
return 0;
}
// copy the first 512k of flash (32 pages * 16k per page) to DRAM (offset 64k)
print_string(“copying pages of flash to DRAM…\n”);
copy_pages(0x10000,0,0x20);
print_string(“done. Scanning for image in DRAM…\n”);
// the image sits at 0x10000, and the IPL, which was
// at the beginning of the flash, occupies the first 8k
image = image_scan_ext(0x12000, 0x12800);
if(image == 0xffffffff)
{
print_string(“image_scan: no image found\n”);
return(0);
}
print_sl("image scan found image at: ", image);
if (image_setup_ext(image) !=0){
print_string(“image_setup failed\n”);
return(0);
}
image_start_ext();
return(0);
}
//copy_pages.c
asm(".code16gcc");
#include “ipl.h”
#include <string.h>
#include <x86/inout.h>
void my_copy(unsigned long dst, unsigned long src, unsigned long size)
/*
This function converts the src address to a segment and offset,
gets a dword of data, converts the destination address to a
segment and offset, and writes the data there.
*/
{
unsigned long src_seg;
unsigned long src_off;
unsigned long dst_seg;
unsigned long dst_off;
unsigned long data;
unsigned long tmp = 0;
while(size > 0)
{
// get the data from the src address
src_seg = (src >> 4) & ~0xfff;
src_off = src & 0xffff;
asm volatile(
“pushw %%es\n\t”
“movw %1,%%ax\n\t”
“movw %%ax,%%es\n\t”
“movl %%es:(%2), %%eax\n\t”
“popw %%es\n\t”
:"=a" (data)
:“m” (src_seg), “r”(src_off)
:“memory”
);
// figure out the destination seg and offset, and copy the data there
dst_seg = (dst >> 4) & ~0xfff;
dst_off = dst & 0xffff;
asm volatile(
“pushw %%es\n\t”
“movw %0,%%ax\n\t”
“movw %%ax,%%es\n\t”
“movl %1,%%eax\n\t”
“movl %%eax,%%es:(%2)\n\t”
“popw %%es\n\t”
:
:“m” (dst_seg), “r” (data), “r” (dst_off)
:“eax”,“memory”
);
dst += 4;
src += 4;
size -= 4;
}
}
void copy_pages(unsigned long dest, int start_page, int end_page)
/*
Copy the specified number of flash pages to DRAM
*/
{
int i;
for(i = start_page; i < end_page; i++)
{
// set up the proper page
out8(0x20c, i & 0xff);
// each page is 16k (0x4000), and the flash window sits at 0xD8000
my_copy(dest,0xd8000,0x4000);
dest += 0x4000;
}
}
If you have trouble with the code in the my_copy() function, you might try
using the int15_copy() function instead, which is part of the IPL library. It uses
the BIOS int15 function 87 call to copy a block of memory from an address above
1M when in real mode. It’s normally called in image_scan_ext() and image_setup_ext()
when booting from linear flash which is mapped above 1M, but it should work
when both the source and destination addresses are below 1M, as is the case here.
The prototype is:
unsigned char int15_copy(long from, long to, long len);
Hope this helps,
Dave
This piece of code works after QNX boot:
int main( void )
{
unsigned char *addr, *buff;
int i;
_uintptr map;
ThreadCtl( _NTO_TCTL_IO, 0 );
map = mmap_device_io( 1, (_uint64) 0x20C ); // paging address
out8( map, 0 );
addr = (unsigned char *) mmap( 0, 0x2000, PROT_READ, MAP_SHARED | MAP_PHYS,
NOFD, 0xD8000 );
assert( addr != MAP_FAILED );
buff = addr;
for( i = 0; i < 256; i++, buff++ )
printf( “[%02x]”, *buff );
return 0;
}
But this ipl code does not work…
int image_download_my_flash( unsigned dst_address )
{
unsigned char *src, *dst, i;
unsigned j;
(int)dst = dst_address;
for( i = 1; i < 128; i++ ) // read 127 pages starting from 1
{
out8( 0x20c, i );
for( j = 0, (int)src = 0xD8000; j < 0x8000; j++, dst++, src++ )
*dst = *src;
}
return 0;
}
Regards,
Ricardo Kazumi Ashikawa
–
Dave Green (dgreen@qnx.com)
QNX Software Systems Ltd.
http://www.qnx.com