From: Cord S. <cs...@em...> - 2001-11-21 17:01:27
|
Hi everyone, I'm new to Linux on SH and try to get a custom board running. I am using the 2.4.13 kernel from the LinuxSH CVS and can load it up to my board. I managed to hack the serial console to come out on the HD64465 UART (the only serial line connected on my board). The kernel boots and find some minimal hardware. Since I don't have network yet, I want to load an initrd/ramdisk with the kernel image. Can anyone provide me with some hints on how to do this for the SH environment? Thanks for any help. Cord |
From: Stuart M. <Stu...@st...> - 2001-11-21 18:34:38
|
Cord Its pretty simple. Assuming you have a ramdisk image, you simply need to load it into memory, and tell the kernel where it is: - loading will depend on what tools you are using to download your kernel. If you have a loader which supports the downloading of binary files, that it simple. If you are using a tool like gdb, which only supports the downloading of elf files, or a loader which can only use S-records or similar, ld or objcopy can be used to convert to the appropriate format. The image needs to be loaded into memory which the kernel knows about, so don't try and load the image into what, for the kernel's point of view, is unused memory. - telling the kernel where the image is simply involves modifying a few workds of memory near the start of the kernel image. These corrispond to the C symbol empty_zero_page, which is 4K from the start of kernel memory: empty_zero_page + 0x00: mount root read only + 0x04: ramdisk flags + 0x08: root device + 0x0c: loader type + 0x10: initrd start + 0x14: initrd size + 0x100: kernel command line The only words you should need to modify are: + 0x0c: loader type - set to 1 + 0x10: initrd start - set to the offset of the image from the start of kernel memory (CONFIG_MEMORY_START) + 0x14: initrd size - size of the initrd image Again, how you do this depends of what tools you are using. You might want to have a look at the gdb start up scripts which are part of the CVS kernel sources, in the root of the kernel sources - .gdbinit-dmida is a well commented example. Hope this helps Stuart On Nov 21, 6:01pm, cs...@em... wrote: > Subject: [linuxsh-dev] How to use an initrd? > Hi everyone, > > I'm new to Linux on SH and try to get a custom board running. I am using the > 2.4.13 kernel from the LinuxSH CVS and can load it up to my board. I managed > to hack the serial console to come out on the HD64465 UART (the only serial > line connected on my board). The kernel boots and find some minimal hardware. > Since I don't have network yet, I want to load an initrd/ramdisk with the > kernel image. Can anyone provide me with some hints on how to do this for the > SH environment? > > Thanks for any help. > > Cord > > _______________________________________________ > linuxsh-dev mailing list > lin...@li... > https://lists.sourceforge.net/lists/listinfo/linuxsh-dev > > >-- End of excerpt from cs...@em... |
From: Cord S. <cs...@em...> - 2001-11-21 20:43:32
|
Hi Stuart, many thanks for the detailed help. Still some questions, s. below: On Wed, 21 Nov 2001, Stuart Menefy wrote: > Cord > > Its pretty simple. Assuming you have a ramdisk image, you simply need > to load it into memory, and tell the kernel where it is: > > - loading will depend on what tools you are using to download your kernel. > If you have a loader which supports the downloading of binary files, > that it simple. If you are using a tool like gdb, which only supports > the downloading of elf files, or a loader which can only use S-records > or similar, ld or objcopy can be used to convert to the appropriate > format. I've to use S-records, which I generate with objcopy. But the loader only permits one upload with one start address. Guess, I've to combine two S-records into one file. That should work, shouldn't it? > The image needs to be loaded into memory which the kernel knows about, > so don't try and load the image into what, for the kernel's point of > view, is unused memory. The address is not important? I.e. right after the compressed image or near the upper limit of RAM? How does the kernel know where to move the uncompressed data to? Can it be compressed at all? At offset 0x14 below, the initrd size corresponds to the image in RAM after uploading, doesn't it? > - telling the kernel where the image is simply involves modifying > a few workds of memory near the start of the kernel image. These > corrispond to the C symbol empty_zero_page, which is 4K from the > start of kernel memory: > > empty_zero_page + 0x00: mount root read only > + 0x04: ramdisk flags > + 0x08: root device > + 0x0c: loader type > + 0x10: initrd start > + 0x14: initrd size > + 0x100: kernel command line > > The only words you should need to modify are: > + 0x0c: loader type - set to 1 > + 0x10: initrd start - set to the offset of the image from the start > of kernel memory (CONFIG_MEMORY_START) > + 0x14: initrd size - size of the initrd image Yes, I've found the ezp, but I thought it would be more difficult ;-) > Again, how you do this depends of what tools you are using. You might > want to have a look at the gdb start up scripts which are part of the > CVS kernel sources, in the root of the kernel sources - .gdbinit-dmida > is a well commented example. I'll look at it. > Hope this helps Definitely. Thanks again! Cord |
From: Stuart M. <Stu...@st...> - 2001-11-22 12:16:51
|
On Nov 21, 9:42pm, cs/internet////////RFC-822/cs#a#emlix#f#com@hemloc wrote: > Subject: Re: [linuxsh-dev] How to use an initrd? > Hi Stuart, > > many thanks for the detailed help. Still some questions, s. below: > > On Wed, 21 Nov 2001, Stuart Menefy wrote: > > > Cord > > > > Its pretty simple. Assuming you have a ramdisk image, you simply need > > to load it into memory, and tell the kernel where it is: > > > > - loading will depend on what tools you are using to download your kernel. > > If you have a loader which supports the downloading of binary files, > > that it simple. If you are using a tool like gdb, which only supports > > the downloading of elf files, or a loader which can only use S-records > > or similar, ld or objcopy can be used to convert to the appropriate > > format. > > I've to use S-records, which I generate with objcopy. But the loader only > permits one upload with one start address. Guess, I've to combine two > S-records into one file. That should work, shouldn't it? Yep, S-records have the address for each line, so simply concatinating them should work fine. > > The image needs to be loaded into memory which the kernel knows about, > > so don't try and load the image into what, for the kernel's point of > > view, is unused memory. > > The address is not important? I.e. right after the compressed image or near > the upper limit of RAM? How does the kernel know where to move the > uncompressed data to? Can it be compressed at all? At offset 0x14 below, the > initrd size corresponds to the image in RAM after uploading, doesn't it? Correct, the address is not important. However it does need to be above the kernel text and data, plus the kernel's page map, so near the top of memory is good. The way this works: - kernel sets up free page list for the whole of memory. Initially all pages are free, so the next thing it does is mark the kernel code and data pages, plus the pages the page list itself occupies, as in use. - the kernel then marks the initrd memory as in use (which is why it needs to be part of the known memory map). - the image is then decompressed, pages for the decompressed image just being allocated as normal from the free page list. - finally the initrd memory is marked as free So the decompressed image can be anywhere in memory, you don't need to known or care. Yes, it can be compressed, just use gzip. The initrd size at offset 0x14 corrisponds to the compressed size (it is this which is used to mark the initrd pages as occupied in the second step above). One thing I did forget to mention, which may be causing some confusion. The final ram disk size is fixed (ie it does not expand to accomodate whatever data you put in it), although the memory it occupies is only allocated as required. The default size is chosen when you configure the kernel (CONFIG_BLK_DEV_RAM_SIZE) and is usually 4M. However it can also be overridden from the kernel command line with the "ramdisk_size=xxx" option, where xxx is the size in K. One other thing I should have mentioned. There is a good description of how to create the initrd image in Documentation/initrd.txt in the kernel source tree. > > - telling the kernel where the image is simply involves modifying > > a few workds of memory near the start of the kernel image. These > > corrispond to the C symbol empty_zero_page, which is 4K from the > > start of kernel memory: > > > > empty_zero_page + 0x00: mount root read only > > + 0x04: ramdisk flags > > + 0x08: root device > > + 0x0c: loader type > > + 0x10: initrd start > > + 0x14: initrd size > > + 0x100: kernel command line > > > > The only words you should need to modify are: > > + 0x0c: loader type - set to 1 > > + 0x10: initrd start - set to the offset of the image from the start > > of kernel memory (CONFIG_MEMORY_START) > > + 0x14: initrd size - size of the initrd image > > Yes, I've found the ezp, but I thought it would be more difficult ;-) > > > Again, how you do this depends of what tools you are using. You might > > want to have a look at the gdb start up scripts which are part of the > > CVS kernel sources, in the root of the kernel sources - .gdbinit-dmida > > is a well commented example. > > I'll look at it. > > > Hope this helps > > Definitely. Thanks again! > Cord > > _______________________________________________ > linuxsh-dev mailing list > lin...@li... > https://lists.sourceforge.net/lists/listinfo/linuxsh-dev > > >-- End of excerpt from cs/internet////////RFC-822/cs#a#emlix#f#com@hemloc |
From: Cord S. <cs...@em...> - 2001-11-22 19:00:27
|
Hi Stuart, On Thu, 22 Nov 2001, Stuart Menefy wrote: [..] > Yep, S-records have the address for each line, so simply concatinating > them should work fine. Yes, works. I just need to manipulate S0 and S7 records. > > > The image needs to be loaded into memory which the kernel knows about, > > > so don't try and load the image into what, for the kernel's point of > > > view, is unused memory. > > > > The address is not important? I.e. right after the compressed image or near > > the upper limit of RAM? How does the kernel know where to move the > > uncompressed data to? Can it be compressed at all? At offset 0x14 below, the > > initrd size corresponds to the image in RAM after uploading, doesn't it? > > Correct, the address is not important. However it does need to be above > the kernel text and data, plus the kernel's page map, so near the top of > memory is good. > > The way this works: > - kernel sets up free page list for the whole of memory. Initially all > pages are free, so the next thing it does is mark the kernel code and > data pages, plus the pages the page list itself occupies, as in use. > - the kernel then marks the initrd memory as in use (which is why it needs > to be part of the known memory map). > - the image is then decompressed, pages for the decompressed image just > being allocated as normal from the free page list. > - finally the initrd memory is marked as free That makes things more clear, thanks. But there're still problems (s. below). > So the decompressed image can be anywhere in memory, you don't need to > known or care. > > Yes, it can be compressed, just use gzip. Ah, I had a closer look and found the autodetection routine. > The initrd size at offset 0x14 corrisponds to the compressed size (it > is this which is used to mark the initrd pages as occupied in the second > step above). > > One thing I did forget to mention, which may be causing some confusion. > The final ram disk size is fixed (ie it does not expand to accomodate > whatever data you put in it), although the memory it occupies is only > allocated as required. > > The default size is chosen when you configure the kernel > (CONFIG_BLK_DEV_RAM_SIZE) and is usually 4M. However it can also be > overridden from the kernel command line with the "ramdisk_size=xxx" option, > where xxx is the size in K. That option is *not* parsed in arch/sh/kernle/setup.c. > One other thing I should have mentioned. There is a good description > of how to create the initrd image in Documentation/initrd.txt in the > kernel source tree. Yes, I've found that, but was wondering how to set things up without the help of a LILO. > > > - telling the kernel where the image is simply involves modifying > > > a few workds of memory near the start of the kernel image. These > > > corrispond to the C symbol empty_zero_page, which is 4K from the > > > start of kernel memory: > > > > > > empty_zero_page + 0x00: mount root read only > > > + 0x04: ramdisk flags > > > + 0x08: root device > > > + 0x0c: loader type > > > + 0x10: initrd start > > > + 0x14: initrd size > > > + 0x100: kernel command line > > > > > > The only words you should need to modify are: > > > + 0x0c: loader type - set to 1 > > > + 0x10: initrd start - set to the offset of the image from the start > > > of kernel memory (CONFIG_MEMORY_START) > > > + 0x14: initrd size - size of the initrd image > > > > Yes, I've found the ezp, but I thought it would be more difficult ;-) Besides all the great tips, initrd doesn't work for me.... Here's my empty_zero_page setup (arch/sh/kernel/head.S): .section .empty_zero_page, "aw" ENTRY(empty_zero_page) .long 1 /* MOUNT_ROOT_RDONLY */ .long 0 /* RAMDISK_FLAGS */ .long 0x0100 /* ORIG_ROOT_DEV */ .long 1 /* LOADER_TYPE */ .long 0x00300000 /* INITRD_START */ .long 0x00100000 /* INITRD_SIZE */ .long 0 #ifdef CONFIG_CMDLINE_BOOL .balign 0x100,0,0x100 /* COMMAND_LINE */ .string "mem=16m console=ttyS0,115200n8 init=/bin/sh" ! .string CONFIG_CMDLINE #endif /* CONFIG_CMDLINE_BOOL */ .balign 4096,0,4096 My problem is, that the ezp somehow is not filled correctly after decompressing the kernel. I put a hexdump right at the top of arch/sh/kernel/setup_arch() and there's still some text strings from the bootloader... (no commandline either). Anyone an idea, why? Therefore all initrd setup with INITRD_START, etc. goes wrong. But even if I hardcode the above values to INITRD_START and INITRD_SIZE, which leads to correct values in the calls to reserve_bootmem_node(), the loading fails. What I found ist that in initrd_load() the offset for rd_load_image() is taken from rd_image_start, which in turn of the broken ezp is also broken. Why is rd_image_start relevant for an initrd? Any ideas? Thanks. Cord |
From: Alessandro R. <ru...@gn...> - 2001-11-22 12:19:08
|
> I've to use S-records, which I generate with objcopy. But the loader only > permits one upload with one start address. Guess, I've to combine two > S-records into one file. That should work, shouldn't it? You can also link the ramdisk inside the kernel. I've done that for mips one year ago (it was the standard for PDA devices), and I'm going to it today or tomorrow on my sh box. What you should do is this: - convert the ext2/whatever image to an object file with objcopy and set the __rd_start and __rd_end symbols - link it in by adding the object file to the Makefile - add this in place of the code that uses the empy_zero_page header: extern void * __rd_start, * __rd_end; initrd_start = (unsigned long)&__rd_start; initrd_end = (unsigned long)&__rd_end; initrd_below_start_ok = 1; That should work. If you or someone else is interested in my implementation, I'll post the real code and script tomorrow. /alessandro |
From: Cord S. <cs...@em...> - 2001-11-22 19:01:09
|
Hi Alessandro, On Thu, 22 Nov 2001, Alessandro Rubini wrote: > > > I've to use S-records, which I generate with objcopy. But the loader only > > permits one upload with one start address. Guess, I've to combine two > > S-records into one file. That should work, shouldn't it? > > You can also link the ramdisk inside the kernel. I've done that for > mips one year ago (it was the standard for PDA devices), and I'm going > to it today or tomorrow on my sh box. > > What you should do is this: > - convert the ext2/whatever image to an object file with > objcopy and set the __rd_start and __rd_end symbols > - link it in by adding the object file to the Makefile > - add this in place of the code that uses the empy_zero_page header: > > extern void * __rd_start, * __rd_end; > initrd_start = (unsigned long)&__rd_start; > initrd_end = (unsigned long)&__rd_end; > initrd_below_start_ok = 1; > > That should work. If you or someone else is interested in my > implementation, I'll post the real code and script tomorrow. Yes, please. Since I'm having wired problems with initrd (see my response to Stuart), I would try your way next. Is the SH port perhaps missing something for initrd to work? Cord |
From: Alessandro R. <ru...@gn...> - 2001-11-23 10:40:39
|
>> That should work. If you or someone else is interested in my >> implementation, I'll post the real code and script tomorrow. > > Yes, please. Ok. This morning I managed to populate my ramdisk and boot, it works fine, however the SCIF interrupts are not registered so I can't send input to my shell (I only see SCI in /proc/interrupts). This is because I use SCIF as console, and is independent of the ramdisk problem. BTW: can someone please point me to a libc suited for cross-compiling? Building one is tedious, and with the available packages I only managed to compile with horrible -I and -L arguments to the target, but only statical linking was possible. Thanks. Like you, I have no full-featured boot loader, yet. I boot via an eprom tailoerd for vxworks and I can only load a single ELF file from disk. At the end you find the short patch that I used to make initrd work. To convert the ramdisk to object file, use this Makefile: all: ramdisk.o cp $^ linux/arch/sh/boot ramdisk.o: ramdisk.gz sh4eb-linux-ld -r -T ramdisk.lds -b binary \ -o $@ $^ ramdisk.gz: ramdisk gzip < $^ > $@ ramdisk.lds is here: OUTPUT_FORMAT("elf32-shbig-linuxs") OUTPUT_ARCH(sh) SECTIONS { .data : { __rd_start = .; *(.data) __rd_end = .; } } The patch does what I described last time, plus it disables freeing the ramdisk because it isn't aligned (I know it can be aligned somehow, I just didn't go further on that path), so such freeing released valuable memory as well and the kernel locked hard right after mounting the fs; most likely because some allocation overwritten valuable data. Please note that the patch uses a new CONFIG option for the platform we are using. It's pretty dirty stuff, but it works fine to boot with a single file if you can't do anything else. --- ./arch/sh/kernel/Makefile.orig Thu Nov 22 02:04:17 2001 +++ ./arch/sh/kernel/Makefile Thu Nov 22 02:05:07 2001 @@ -23,6 +23,8 @@ obj-$(CONFIG_SH_RTC) += rtc.o obj-$(CONFIG_SH_DMA) += dma.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o +obj-$(CONFIG_BLK_DEV_INITRD) += ../boot/ramdisk.o + ifeq ($(CONFIG_PCI),y) ifeq ($(CONFIG_SH_DREAMCAST),y) --- ./arch/sh/kernel/setup.c.orig Thu Nov 22 02:08:16 2001 +++ ./arch/sh/kernel/setup.c Thu Nov 22 02:18:05 2001 @@ -438,6 +438,15 @@ reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE); #ifdef CONFIG_BLK_DEV_INITRD +#ifdef CONFIG_SH_GX8TSU + { + extern void * __rd_start, * __rd_end; + + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; + initrd_below_start_ok = 1; + } +#else if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE); @@ -452,6 +461,7 @@ initrd_start = 0; } } +#endif /* GX8TSU */ #endif #if 0 --- ./arch/sh/mm/init.c.orig Thu Nov 22 16:04:36 2001 +++ ./arch/sh/mm/init.c Thu Nov 22 16:05:32 2001 @@ -193,6 +193,7 @@ #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { +#if 0 /* GX8 tmp hack */ unsigned long p; for (p = start; p < end; p += PAGE_SIZE) { ClearPageReserved(virt_to_page(p)); @@ -201,6 +202,7 @@ totalram_pages++; } printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); +#endif } #endif |
From: Stuart M. <Stu...@st...> - 2001-11-23 10:59:57
|
On Nov 22, 7:55pm, cs/internet////////RFC-822/cs#a#emlix#f#com@hemloc wrote: > Subject: Re: [linuxsh-dev] How to use an initrd? > Hi Stuart, > > On Thu, 22 Nov 2001, Stuart Menefy wrote: > > [..] > > One thing I did forget to mention, which may be causing some confusion. > > The final ram disk size is fixed (ie it does not expand to accomodate > > whatever data you put in it), although the memory it occupies is only > > allocated as required. > > > > The default size is chosen when you configure the kernel > > (CONFIG_BLK_DEV_RAM_SIZE) and is usually 4M. However it can also be > > overridden from the kernel command line with the "ramdisk_size=xxx" option, > > where xxx is the size in K. > > That option is *not* parsed in arch/sh/kernle/setup.c. It is however parsed in drivers/block/rd.c > > One other thing I should have mentioned. There is a good description > > of how to create the initrd image in Documentation/initrd.txt in the > > kernel source tree. > > Yes, I've found that, but was wondering how to set things up without the help > of a LILO. Sorry, my mistake. I should have said Documentation/ramdisk.txt. What I was referring to was simply the bit at the end which describes how to create the ramdisk image. > Besides all the great tips, initrd doesn't work for me.... > Here's my empty_zero_page setup (arch/sh/kernel/head.S): > > .section .empty_zero_page, "aw" > ENTRY(empty_zero_page) > .long 1 /* MOUNT_ROOT_RDONLY */ > .long 0 /* RAMDISK_FLAGS */ > .long 0x0100 /* ORIG_ROOT_DEV */ > .long 1 /* LOADER_TYPE */ > .long 0x00300000 /* INITRD_START */ > .long 0x00100000 /* INITRD_SIZE */ > .long 0 > > #ifdef CONFIG_CMDLINE_BOOL > .balign 0x100,0,0x100 /* COMMAND_LINE */ > .string "mem=16m console=ttyS0,115200n8 init=/bin/sh" > ! .string CONFIG_CMDLINE > #endif /* CONFIG_CMDLINE_BOOL */ > > .balign 4096,0,4096 > > My problem is, that the ezp somehow is not filled correctly after > decompressing the kernel. I put a hexdump right at the top of > arch/sh/kernel/setup_arch() and there's still some text strings from the > bootloader... (no commandline either). Anyone an idea, why? If you are using the compressed kernel, then one of the things which happens while compressing the kernel code, is that the ezp gets stripped off. Have a look for the objcopy in arch/sh/boot/compressed/Makefile. Either: - boot the uncompressed kernel - modify the Makefile to not strip ezp (and remember to change the initial value of output_ptr to reflect the fact that the kernel should be decompressed lower into memory) - hack misc.c to init the ezp - or get your loader to initialise ezp. > Therefore all initrd setup with INITRD_START, etc. goes wrong. But even if I > hardcode the above values to INITRD_START and INITRD_SIZE, which leads to > correct values in the calls to reserve_bootmem_node(), the loading fails. > > What I found ist that in initrd_load() the offset for rd_load_image() is taken > from rd_image_start, which in turn of the broken ezp is also broken. Why is > rd_image_start relevant for an initrd? This code was origionally written to support loading of a ramdisk from a floppy disk. So rd_image_start is the offset (in blocks) into the device which holds the ramdisk image. For an initrd image this must be 0. This is initialised in arch/sh/kernel/setup.c from RAMDISK_FLAGS, which is read from ezp + 0x04. So if your ezp is not being set up, I suspect this value is ending up as non-zero, and when trying to decompress the ramdisk image the kernel is not looking at the beginning of the image but at some offset into it. Stuart |