LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [patch 5/6] Update the 83xx/85xx/86xx boards device tree
From: Zang Roy-r61911 @ 2007-07-11  2:53 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <FFEC5443-109B-45B7-80CA-0252F9365B55@kernel.crashing.org>

On Wed, 2007-07-11 at 04:28, Segher Boessenkool wrote:
> > Indentify pci, pcie host by compatible property
> > "fsl,mpc83xx-pci","83xx"
> > "fsl,mpc85xx-pci","85xx"
> > "fsl,mpc86xx-pci","86xx"
> > and
> > "fsl, mpc85xx-pciex","85xx"
> > "fsl, mpc86xx-pciex","86xx"
> 
> This can't ever work -- 
It works!
> if you see "compatible" = "85xx",
> what is it?
That's why I remove the original compatible "85xx".

>   PCI or PCIe?  Or something else perhaps, maybe
> a CPU or an I2C controller or who-knows-what?
I just think the compatible field
"fsl,mpc83xx-pci","83xx"
has some redundant information.
Kumar don't want to break anything using the old  
information.  
We can remove it in the future:-).
Roy

^ permalink raw reply

* Re: [PATCH 1/1] libata: pata_pdc2027x PLL input clock fix
From: Albert Lee @ 2007-07-11  2:45 UTC (permalink / raw)
  To: Mikael Pettersson
  Cc: dwm, jeff, linux-ide, bahadir.balban, linuxppc-dev, alan
In-Reply-To: <200707102314.l6ANEWq2029195@harpo.it.uu.se>

Mikael Pettersson wrote:
> 
> 
> 2.6.22 + this prints the following on my G3:
> 
> pata_pdc2027x 0000:00:0e.0: version 0.9
> usec_elapsed for mdelay(37) [35431]
> start time: [1184112028]s [775333]us 
> end   time: [1184112028]s [810764]us 
> pata_pdc2027x 0000:00:0e.0: PLL input clock 1691741 kHz
> pata_pdc2027x: Invalid PLL input clock 1691741kHz, give up!
> 

My x86 box got this:
Jul 11 10:02:17 p4ht-s kernel: [  260.746980] ACPI: PCI Interrupt 0000:02:05.0[A] -> Link [LNK1] -> GSI 10 (level, low) -> IRQ 10
Jul 11 10:02:17 p4ht-s kernel: [  260.882905] usec_elapsed for mdelay(37) [36734]
Jul 11 10:02:17 p4ht-s kernel: [  260.882911] start time: [1184119336]s [999802]us 
Jul 11 10:02:17 p4ht-s kernel: [  260.882914] end   time: [1184119337]s [36536]us 
Jul 11 10:02:17 p4ht-s kernel: [  260.882917] pata_pdc2027x 0000:02:05.0: PLL input clock 16829 kHz

So, it seems both mdelay(37) and do_gettimeofday() are working properly on PowerMac G3.
Maybe the calculated wrong PLL input is due to wrong reading of the counter register?
Could you please try the attached debug patch for more clue, thanks.

--
albert

diff -Nrup 00_libata-dev/drivers/ata/pata_pdc2027x.c 01_debug/drivers/ata/pata_pdc2027x.c
--- 00_libata-dev/drivers/ata/pata_pdc2027x.c	2007-07-07 09:58:55.000000000 +0800
+++ 01_debug/drivers/ata/pata_pdc2027x.c	2007-07-11 10:41:41.000000000 +0800
@@ -574,8 +574,8 @@ retry:
 
 	counter = (bccrh << 15) | bccrl;
 
-	PDPRINTK("bccrh [%X] bccrl [%X]\n", bccrh,  bccrl);
-	PDPRINTK("bccrhv[%X] bccrlv[%X]\n", bccrhv, bccrlv);
+	printk(KERN_ERR "bccrh [%X] bccrl [%X]\n", bccrh,  bccrl);
+	printk(KERN_ERR "bccrhv[%X] bccrlv[%X]\n", bccrhv, bccrlv);
 
 	/*
 	 * The 30-bit decreasing counter are read by 2 pieces.
@@ -584,7 +584,7 @@ retry:
 	 */
 	if (retry && !(bccrh == bccrhv && bccrl >= bccrlv)) {
 		retry--;
-		PDPRINTK("rereading counter\n");
+		printk(KERN_ERR "rereading counter\n");
 		goto retry;
 	}
 
@@ -722,8 +722,21 @@ static long pdc_detect_pll_input_clock(s
 	pll_clock = (start_count - end_count) / 100 *
 		(100000000 / usec_elapsed);
 
-	PDPRINTK("start[%ld] end[%ld] \n", start_count, end_count);
-	PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock);
+	printk(KERN_ERR "start[%ld] end[%ld] \n", start_count, end_count);
+	printk(KERN_ERR "usec_elapsed for mdelay(100) [%ld]\n", usec_elapsed);
+	printk(KERN_ERR "start time: [%ld]s [%ld]us \n", start_time.tv_sec, start_time.tv_usec);
+	printk(KERN_ERR "end   time: [%ld]s [%ld]us \n", end_time.tv_sec, end_time.tv_usec);
+	printk(KERN_ERR "PLL input clock[%ld]Hz\n", pll_clock);
+
+	/* mdelay(37) for comparison */
+	do_gettimeofday(&start_time);
+	mdelay(37);
+	do_gettimeofday(&end_time);
+	usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
+		(end_time.tv_usec - start_time.tv_usec);
+	printk(KERN_ERR "usec_elapsed for mdelay(37) [%ld]\n", usec_elapsed);
+	printk(KERN_ERR "start time: [%ld]s [%ld]us \n", start_time.tv_sec, start_time.tv_usec);
+	printk(KERN_ERR "end   time: [%ld]s [%ld]us \n", end_time.tv_sec, end_time.tv_usec);
 
 	return pll_clock;
 }

^ permalink raw reply

* Re: [patch 3/6] Add 8548 CDS PCI express controller node and PCI-X device node
From: Zang Roy-r61911 @ 2007-07-11  2:44 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <963D5B48-F1E5-4930-9F29-98D7F0E33C0A@kernel.crashing.org>

On Wed, 2007-07-11 at 04:25, Segher Boessenkool wrote:
> >               pci1: pci@8000 {
> >                       interrupt-map-mask = <1f800 0 0 7>;
> 
> Set the mask to <1800 0 0 7>, and you need only 16
> entries to encode the swizzle.  Except...
> 
> > +                             /* bus 1 , idsel 0x2 Tsi310 bridge
> secondary */
> 
> ...interrupts on bus 1 should be swizzled on bus 1, not
> at the PHB.  Really.  It is a horrible workaround for a
> non-existing problem to do it here, and I promise you
> it _will_ come back to hurt you later.  Not a threat,
> just a promise :-)

I just want to make it as a temporary workaround now.
Extra patches will be provided to fix it.


> > -                     compatible = "85xx";
> > +                     compatible = "fsl,mpc85xx-pci","85xx";
> 
> No more "xx" please...
> 
> > +             pci@a000 {
> > +                     interrupt-map-mask = <f800 0 0 7>;
> > +                     interrupt-map = <
> > +
> > +                             /* IDSEL 0x0 (PEX) */
> > +                             00000 0 0 1 &mpic 0 1
> > +                             00000 0 0 2 &mpic 1 0
> > +                             00000 0 0 3 &mpic 2 0
> > +                             00000 0 0 4 &mpic 3 0>;
> 
> Why sense 0 for all but the first entry in this map?
Now, only the first entry is used.
> 
> > +                     compatible = "fsl,mpc86xx-pciex","86xx";
> 
> And "xx" again.  Aren't the 85- and 86- PCIe controllers
> compatible, btw?

^ permalink raw reply

* Re: [PATCH v2] Consolidate mm_context_t definition in mmu.h
From: Josh Boyer @ 2007-07-11  2:22 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, arnd, david
In-Reply-To: <18068.4589.614583.210312@cargo.ozlabs.ibm.com>

On Wed, Jul 11, 2007 at 09:10:37AM +1000, Paul Mackerras wrote:
> Josh Boyer writes:
> 
> > All of the platforms except PPC64 share a common mm_context_t definition.
> > Defining it in mmu.h avoids duplicating it in the platform specific mmu
> > header files.  We further consolidate it by having the PPC32 definition
> > share the mm_context_id_t type for the id member.
> 
> Unfortunately the string of ifdefs in your consolidated version makes
> my eyes water.  I'm not sure it isn't better the way it is.

Eh, you're the maintainer.  No worries.

Though realistically, I only added a single ifdef set in the structure.  The
rest are all Ben's ;)

josh

^ permalink raw reply

* Missed serial patch breaks arch/powerpc 44x port
From: Josh Boyer @ 2007-07-11  2:17 UTC (permalink / raw)
  To: paulus, akpm; +Cc: linuxppc-dev, david

Hi All,

When support for the PPC44x arch/powerpc port was posted back in May, David
included two serial patches along with it.  The short story is that the
powerpc patches were merged in via Paul, but the two serial patches were never
merged.  This makes the 44x arch/powerpc port dead on arival in 2.6.22.

The two patches I speak of are:

http://patchwork.ozlabs.org/linuxppc/patch?person=11&id=10935

and

http://patchwork.ozlabs.org/linuxppc/patch?person=11&id=10934

Unfortunately, the fact that the second patch is missing breaks the Ebony
board, manifesting itself in a machine check during boot.  The lack of using
resource_size_t for the mapbase member of the uart_port structure means that
the physical address passed in is too large for the data type and the wrong
address gets ioremapped.

Could we get those patches, particularly the second one, merged during the
merge window?  We might also want to push them to -stable.

The alternative would be to re-introduce the fixup_big_phys_addr function in
the 44x ioremap path.  I'd rather avoid adding that back in temporarily if
these serial patches are eventually going to go in anyway.

josh

^ permalink raw reply

* Re: [patch 3/6] Add 8548 CDS PCI express controller node and PCI-X device node
From: Kumar Gala @ 2007-07-11  2:02 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Paul Mackerras, linuxppc-dev list
In-Reply-To: <963D5B48-F1E5-4930-9F29-98D7F0E33C0A@kernel.crashing.org>


On Jul 10, 2007, at 3:25 PM, Segher Boessenkool wrote:

>>  		pci1: pci@8000 {
>>  			interrupt-map-mask = <1f800 0 0 7>;
>
> Set the mask to <1800 0 0 7>, and you need only 16
> entries to encode the swizzle.  Except...
>
>> +				/* bus 1 , idsel 0x2 Tsi310 bridge secondary */
>
> ...interrupts on bus 1 should be swizzled on bus 1, not
> at the PHB.  Really.  It is a horrible workaround for a
> non-existing problem to do it here, and I promise you
> it _will_ come back to hurt you later.  Not a threat,
> just a promise :-)
>
>> -			compatible = "85xx";
>> +			compatible = "fsl,mpc85xx-pci","85xx";
>
> No more "xx" please...
>
>> +		pci@a000 {
>> +			interrupt-map-mask = <f800 0 0 7>;
>> +			interrupt-map = <
>> +
>> +				/* IDSEL 0x0 (PEX) */
>> +				00000 0 0 1 &mpic 0 1
>> +				00000 0 0 2 &mpic 1 0
>> +				00000 0 0 3 &mpic 2 0
>> +				00000 0 0 4 &mpic 3 0>;
>
> Why sense 0 for all but the first entry in this map?
>
>> +			compatible = "fsl,mpc86xx-pciex","86xx";
>
> And "xx" again.  Aren't the 85- and 86- PCIe controllers
> compatible, btw?

They are, but we need to distinguish between 83xx, 85xx, and 86xx  
pci, pciex, pci-x controllers.

- k

^ permalink raw reply

* Re: [PATCH] pata_mpc52xx: suspend/resume support
From: Jeff Garzik @ 2007-07-11  1:14 UTC (permalink / raw)
  To: Domen Puncer; +Cc: linux-ide, linuxppc-embedded
In-Reply-To: <20070703082738.GM23294@moe.telargo.com>

Domen Puncer wrote:
> Implement suspend and resume routines for mpc52xx ata driver.
> Tested on Lite5200b with deep-sleep and low-power (not yet in-tree)
> modes.
> 
> 
> Signed-off-by: Domen Puncer <domen.puncer@telargo.com>
> 
> ---
> If anyone cares, I attached ATA_DEBUG messages at the end of patch.
> Should it take almost 5 seconds?
> 
> 
>  drivers/ata/pata_mpc52xx.c |   18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)

applied

^ permalink raw reply

* Re: [PATCH] Allow exec on 32-bit from readable, non-exec pages, with a warning.
From: Paul Mackerras @ 2007-07-11  1:02 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <89E626D4-D48D-4062-A996-E2DFFE8248E3@kernel.crashing.org>

Segher Boessenkool writes:

> >> Yeah.  Giving the warning is a good thing though.
> >
> > No, it isn't; it's just noise, if we're not ever going to do anything
> > to prevent the behaviour - and we can't.
> 
> The same userland code will not run correctly on PPC64 or BookE
> systems.  Is that not a reason to warn?

It *will* run on ppc64 systems, because there we get the
READ_IMPLIES_EXEC personality flag set via the elf_read_implies_exec
thing in include/asm-powerpc/elf.h.  The READ_IMPLIES_EXEC flag is
only set if we don't have the non-executable stack note in the ELF
header, i.e. only for old binaries or libraries.

As for Book E, that could be fixed using elf_read_implies_exec too, if
anyone cared.  In fact maybe the correct solution is to have

#define elf_read_implies_exec(ex, exec_stk) \
	(exec_stk != EXSTACK_DISABLE_X) : 0)

for all 32-bit powerpc.

Paul.

^ permalink raw reply

* Re: [PATCH v2] Allow exec on 32-bit from readable, non-exec pages, with a warning.
From: Segher Boessenkool @ 2007-07-11  0:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18066.63111.703924.714899@cargo.ozlabs.ibm.com>

>> In older versions of glibc (through 2.3), the dynamic linker  
>> executes a
>> small amount of code from the data segment, which is not marked as
>> executable.  A recent change (commit  
>> 9ba4ace39fdfe22268daca9f28c5df384ae462cf)
>> stops this from working; there should be a deprecation period before
>> older glibc versions stop working.
>
> Actually I see no good reason to enforce no-exec at all if we can't do
> it consistently.  And if we're not going to enforce it then there is
> no point whinging about it.

I have a new patch with just this behaviour, Scott is
testing it on old glibc (I think it succeeded, need
confirmation though), I'll have it tested on new glibc
tomorrow.  So patch tomorrow, and let's try to forget
about all this after that, eh?  :-)

> When I applied Segher's original patch I thought that we had the
> read-implies-exec stuff enabled for the affected CPUs, but it turns
> out we don't.  (We only have that stuff turned on for 32-bit processes
> on 64-bit cpus - see elf_read_implies_exec in include/asm-powerpc/ 
> elf.h.)

I never thought "real code" would rely on executing stuff
it didn't map as executable before.  Silly me.  In my
defense, no one else noticed in time either ;-)


Segher

^ permalink raw reply

* Re: [PATCH 2.6.21-rt2] PowerPC: decrementer clockevent driver
From: Segher Boessenkool @ 2007-07-11  0:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Thomas Gleixner, mingo, linux-kernel
In-Reply-To: <18068.5829.53635.797336@cargo.ozlabs.ibm.com>

>>> This scales with the number of processors since there is one
>>> decrementer per core (is it per thread on SMT chips?
>>> I don't know).
>>
>> One per core.
>
> No, each thread has its own decrementer, but the timebase is shared.

Argh, of course you're right, I'm reading the wrong ISA
version again.  Sorry.


Segher

^ permalink raw reply

* Re: [PATCH] Allow exec on 32-bit from readable, non-exec pages, with a warning.
From: Segher Boessenkool @ 2007-07-11  0:03 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <18068.5706.700933.551828@cargo.ozlabs.ibm.com>

>> Yeah.  Giving the warning is a good thing though.
>
> No, it isn't; it's just noise, if we're not ever going to do anything
> to prevent the behaviour - and we can't.

The same userland code will not run correctly on PPC64 or BookE
systems.  Is that not a reason to warn?


Segher

^ permalink raw reply

* Re: [PATCH 2.6.21-rt2] PowerPC: decrementer clockevent driver
From: Paul Mackerras @ 2007-07-10 23:31 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Thomas Gleixner, mingo, linux-kernel
In-Reply-To: <78777AB0-8FA2-4FB0-9D02-6504ED28957D@kernel.crashing.org>

Segher Boessenkool writes:

> > This scales with the number of processors since there is one
> > decrementer per core (is it per thread on SMT chips?
> > I don't know).
> 
> One per core.

No, each thread has its own decrementer, but the timebase is shared.

Paul.

^ permalink raw reply

* Re: [PATCH] Allow exec on 32-bit from readable, non-exec pages, with a warning.
From: Paul Mackerras @ 2007-07-10 23:29 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: linuxppc-dev, Arnd Bergmann
In-Reply-To: <8CA741AA-D200-474F-943D-ECE4B3ACD38B@kernel.crashing.org>

Segher Boessenkool writes:

> Yeah.  Giving the warning is a good thing though.

No, it isn't; it's just noise, if we're not ever going to do anything
to prevent the behaviour - and we can't.

Paul.

^ permalink raw reply

* Re: [PATCH] Infinite loop/always true check possible with unsigned counter.
From: Paul Mackerras @ 2007-07-10 23:19 UTC (permalink / raw)
  To: Manish Ahuja; +Cc: ppc-dev
In-Reply-To: <4693D27D.7070504@austin.ibm.com>

Manish Ahuja writes:

> I presume the patch is good then. Do I need to change anything ?

I guess not.  It will cause a warning on the first for loop if anyone
tries to compile with -Wextra or -Wsign-compare, but it would be only
one of lots of warnings in that case (and in fact comparing signed
with unsigned is a perfectly legitimate, well-defined thing to do; you
just have to be aware that the comparison is done as unsigned).

Paul.

^ permalink raw reply

* Re: [PATCH 7/15] bootwrapper: Add kexec callable zImage wrapper
From: Segher Boessenkool @ 2007-07-10 23:16 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
In-Reply-To: <boot-6-07.miltonm@bga.com>

> The memory node off the root with a name starting with "memory" must
> contain enough free memory (not in the reserved ranges) in the first
> reg range to uncompress the the kernel with padding.

There can be many nodes called "/memory".  You probably
want to use the node pointed to by /chosen/memory instead?


Segher

^ permalink raw reply

* Re: [PATCH 1/1] libata: pata_pdc2027x PLL input clock fix
From: Mikael Pettersson @ 2007-07-10 23:14 UTC (permalink / raw)
  To: albertl, mikpe; +Cc: dwm, jeff, linux-ide, bahadir.balban, linuxppc-dev, alan

On Tue, 10 Jul 2007 11:52:59 +0800, Albert Lee wrote:
> >>Recently the PLL input clock of pata_pdc2027x is sometimes detected
> >>higer than expected (e.g. 20.027 MHz compared to 16.714 MHz).
> >>It seems sometimes the mdelay() function is not as precise as it
> >>used to be. Per Alan's advice, HT or power management might affect
> >>the precision of mdelay().
> >>
> >>This patch calls gettimeofday() to mesure the time elapsed and
> >>calculate the PLL input clock accordingly.
> > 
> > 
> > Unfortunately this breaks pata_pdc2027x on my PowerMac G3:
> > 
> <snip>
> > 
> > In fairness, this is a slightly non-standard PowerMac G3, in that it
> > has a G4 upgrade processor. The firmware doesn't recognise the CPU
> > and gives some CPU core frequency-related properties too low values.
> > However, the bus frequency property _is_ correct, which is what
> > most or all timing stuff should be based on.
> > 
> > Looks like a platform bug.
> > 
> 
> According to the document, do_gettimeofday() has microsecond
> resolution. Since the driver calls mdelay(100) (100000 microseconds), 
> it won't affect the PLL input clock calculation much if somehow
> do_gettimeofday() drifts several (say 100) microseconds.
> 
> Could you please apply the attached debug patch and collect more info
> on the PowerMac G3. Hopefully we can have more clue. Thanks.
> --
> albert
> 
> (BTW, maybe opening a bug in bugzilla.kernel.org would help the
> debugging.)
> 
> --- 00_libata-dev/drivers/ata/pata_pdc2027x.c	2007-07-07 09:58:55.000000000 +0800
> +++ 01_debug/drivers/ata/pata_pdc2027x.c	2007-07-10 11:18:38.000000000 +0800
> @@ -722,6 +722,15 @@ static long pdc_detect_pll_input_clock(s
>  	pll_clock = (start_count - end_count) / 100 *
>  		(100000000 / usec_elapsed);
>  
> +	do_gettimeofday(&start_time);
> +	mdelay(37);
> +	do_gettimeofday(&end_time);
> +	usec_elapsed = (end_time.tv_sec - start_time.tv_sec) * 1000000 +
> +		(end_time.tv_usec - start_time.tv_usec);
> +	printk(KERN_ERR "usec_elapsed for mdelay(37) [%ld]\n", usec_elapsed);
> +	printk(KERN_ERR "start time: [%ld]s [%ld]us \n", start_time.tv_sec, start_time.tv_usec);
> +	printk(KERN_ERR "end   time: [%ld]s [%ld]us \n", end_time.tv_sec, end_time.tv_usec);
> +
>  	PDPRINTK("start[%ld] end[%ld] \n", start_count, end_count);
>  	PDPRINTK("PLL input clock[%ld]Hz\n", pll_clock);

2.6.22 + this prints the following on my G3:

pata_pdc2027x 0000:00:0e.0: version 0.9
usec_elapsed for mdelay(37) [35431]
start time: [1184112028]s [775333]us 
end   time: [1184112028]s [810764]us 
pata_pdc2027x 0000:00:0e.0: PLL input clock 1691741 kHz
pata_pdc2027x: Invalid PLL input clock 1691741kHz, give up!

/Mikael

^ permalink raw reply

* Re: [PATCH 11/15] bootwrapper: allow vmlinuz to be an external payload
From: Segher Boessenkool @ 2007-07-10 23:11 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
In-Reply-To: <boot-6-11.miltonm@bga.com>

> Allow the boot wrapper to obtain the vmlinux elf from an external
> platform supplied location instead of embedding it at link time.
>
> When used with the cpio library, the kernel can be stored as a file
> an file in the initramfs, allowing the same (compressed) copy of
> the vmlinux elf to be used for both the kernel to execute and any
> user space tools such as kexec (for reboot), crash dump, or oprofile.

Awesome!


Segher

^ permalink raw reply

* Re: [PATCH v2] Consolidate mm_context_t definition in mmu.h
From: Paul Mackerras @ 2007-07-10 23:10 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev, arnd, david
In-Reply-To: <1184089950.32199.24.camel@weaponx.rchland.ibm.com>

Josh Boyer writes:

> All of the platforms except PPC64 share a common mm_context_t definition.
> Defining it in mmu.h avoids duplicating it in the platform specific mmu
> header files.  We further consolidate it by having the PPC32 definition
> share the mm_context_id_t type for the id member.

Unfortunately the string of ifdefs in your consolidated version makes
my eyes water.  I'm not sure it isn't better the way it is.

Paul.

^ permalink raw reply

* Re: [PATCH 6/15] bootwrapper: switch 64 bit cpus to 32 bit mode
From: Segher Boessenkool @ 2007-07-10 22:57 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, David Gibson
In-Reply-To: <boot-6-06.miltonm@bga.com>

> +	/* Check if the processor is running in 32 bit mode, using
> +	 * only 32 bit instructions which should be safe on 32 and
> +	 * 64 bit processors.
> +	 *
> +	 * Subtract the bottom 32 bits of MSR from the full value
> +	 * recording the result.  Since MSR[SF] is in the high word,
> +	 * the result will be not-equal iff in 32 bit mode (either
> +	 * the processor is a 32 bit processor or MSR[SF] = 0).
> +	 */

The other way around -- the processor is 64-bit and MSR[SF]=1.

Great trick btw! :-)

> +	mfmsr	r0		/* grab whole msr		*/
> +	rlwinm	r8,r0,0,0,31	/* extract bottom word		*/
> +	subf.	r8,r8,r0	/* subtract, same?		*/
> +	beq	0f		/* yes: we are 32 bit mode	*/

The code is fine though.


Segher

^ permalink raw reply

* [PATCH/EXAMPLE 15/15] bootwrapper: example sreset marshalling
From: Milton Miller @ 2007-07-10 22:12 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
In-Reply-To: <boot-6-00.miltonm@bga.com>


An example using the marshalling code that can be entered by sreset.
By linking the marshalling code is at 0 and differentiating a cpu
id from a device tree, it also works for kexec.

Signed-off-by: Milton Miller <miltonm@bga.com>
--- 
For reference only, not intended to be merged.

Index: work.git/arch/powerpc/boot/crt0_sample.S
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ work.git/arch/powerpc/boot/crt0_sample.S	2007-07-10 16:47:25.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2006-2007 Milton Miller, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+	/*
+	 * This can be either a kexec started image or a sreset initiated
+	 * one.  kexec-tools purgatory is suppposed to copy from entry
+	 * point, but instead copies from image start, so put marshal_low
+	 * at address 0.
+	 */
+
+	.globl _zimage_start
+_zimage_start:
+#include "marshal_low.S"
+
+	.org 0x100
+	bl	get_cpu_id
+1:	mflr	0
+	lis	r4,1b@ha
+	addi	r4,r4,1b@l
+	subf	r0,r4,r0
+
+	lis	r4,elected_master@ha
+	addi	r4,r4,elected_master@l
+	add	r4,r4,r0
+2:	lwarx	r6,r0,r4
+	cmpwi	r6,0
+	bge	3f
+	stwcx.	r3,r0,r4
+	bne-	2b
+	lwz	r6,0(r4)
+
+3:	lis	r4,cpus_found@ha
+	addi	r4,r4,cpus_found@l
+	add	r4,r4,r0
+4:	lwarx	r12,r0,r4
+	addi	r12,r12,1
+	stwcx.	r12,r0,r4
+	bne-	4b
+
+	cmpw	r6,r3
+	bne	slave
+
+	mr	r4,r0
+	li	r5,0
+	b	master
+
+
+	.globl	_zimage_start_plat
+_zimage_start_plat:
+	b	_zimage_start_lib
+
+	.weak	get_cpu_id
+get_cpu_id:
+
+get_pir:
+	mfspr	r3,1023	/* SPRN_PIR */
+	blr
+
+	.balign 8
+	.globl elected_master
+elected_master:
+	.long -1
+	.globl cpus_expected
+cpus_expected:
+	.long 8
+	.globl cpus_found
+cpus_found:
+	.long 0
Index: work.git/arch/powerpc/boot/sample.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ work.git/arch/powerpc/boot/sample.c	2007-07-10 16:48:45.000000000 -0500
@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright IBM Corporation 2007
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ */
+
+#include "ops.h"
+#include "reg.h"
+#include "flatdevtree.h"
+
+extern struct boot_param_header _dtb_start[], _dtb_end[];
+struct boot_param_header *sample_dt_blob;
+
+extern unsigned int get_cpu_id(void);
+extern unsigned int cpus_found, cpus_expected;
+
+void platform_init(unsigned long boot_cpu_id)
+{
+	if (boot_cpu_id > 1024) {
+		sample_dt_blob = (void *)boot_cpu_id;
+		boot_cpu_id = get_cpu_id();
+	}
+
+	if (!sample_dt_blob)
+		if (_dtb_start != _dtb_end)
+			sample_dt_blob = _dtb_start;
+
+	if (!sample_dt_blob)
+		sample_dt_blob = 31 * 1024 * 1024 + (void *)0;
+
+	if (sample_dt_blob->magic != OF_DT_HEADER)
+		fatal("No device tree at %p\n", sample_dt_blob);
+
+	if (sample_dt_blob->version < 2)
+		conv_flattree_inplace(sample_dt_blob);
+
+	sample_dt_blob->boot_cpuid_phys = boot_cpu_id;
+
+	if (cpus_found && cpus_found < cpus_expected) {
+		HMT_LOW;
+		while (cpus_found < cpus_expected) {
+			barrier();
+		}
+		HMT_MEDIUM;
+	}
+
+	kexec_platform_init(sample_dt_blob);
+}
Index: work.git/arch/powerpc/boot/Makefile
===================================================================
--- work.git.orig/arch/powerpc/boot/Makefile	2007-07-10 16:41:01.000000000 -0500
+++ work.git/arch/powerpc/boot/Makefile	2007-07-10 16:47:45.000000000 -0500
@@ -48,7 +48,7 @@ src-wlib := string.S crt0.S stdio.c main
 		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c
 src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \
 		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
-		ps3-head.S ps3-hvcall.S ps3.c
+		ps3-head.S ps3-hvcall.S ps3.c crt0_sample.S sample.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -128,7 +128,7 @@ quiet_cmd_wrap	= WRAP    $@
 		$(if $6,$6,vmlinux)
 
 kexec-$(CONFIG_PPC32)			+= zImage.kexec
-kexec-$(CONFIG_PPC64)			+= zImage.kexec64
+kexec-$(CONFIG_PPC64)			+= zImage.kexec64 zImage.sample
 
 image-$(CONFIG_PPC_PSERIES)		+= zImage.pseries
 image-$(CONFIG_PPC_MAPLE)		+= zImage.pseries
Index: work.git/arch/powerpc/boot/wrapper
===================================================================
--- work.git.orig/arch/powerpc/boot/wrapper	2007-07-10 16:41:01.000000000 -0500
+++ work.git/arch/powerpc/boot/wrapper	2007-07-10 16:47:25.000000000 -0500
@@ -139,6 +139,9 @@ kexec)
 kexec64)
     platformo="-e _zimage_start_64 $object/crt0_kexec.o"
     ;;
+sample)
+    platformo="$object/crt0_sample.o $object/sample.o"
+    ;;
 miboot|uboot)
     # miboot and U-boot want just the bare bits, not an ELF binary
     ext=bin

^ permalink raw reply

* [PATCH 14/15] boot: add a hook to start cpus
From: Milton Miller @ 2007-07-10 22:12 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
In-Reply-To: <boot-6-00.miltonm@bga.com>

The kexec code is doing strange contortions with dtops.finalize and
platform_ops.vmlinux_alloc to manage the slave cpus.   Add a hook
with the needed information.

Signed-off-by: Milton Miller <miltonm@bga.com>
---
Index: work.git/arch/powerpc/boot/kexec.c
===================================================================
--- work.git.orig/arch/powerpc/boot/kexec.c	2007-07-10 04:39:43.000000000 -0500
+++ work.git/arch/powerpc/boot/kexec.c	2007-07-10 04:40:01.000000000 -0500
@@ -180,32 +180,11 @@ static void init_flat_tree(struct boot_p
 		fatal("Unable to initialize device_tree library!\n\r");
 }
 
-static void *saved_vmlinux_addr;
-
-static void *kexec_vmlinux_alloc(unsigned long size)
-{
-	void *addr;
-
-	addr = ranges_vmlinux_alloc(size);
-
-	saved_vmlinux_addr = addr;
-	return addr;
-}
-
 static void kexec_fixups(void)
 {
 	wait_slaves_moved();
 }
 
-static unsigned long (*finalize_chain)(void);
-
-static unsigned long kexec_finalize(void)
-{
-	send_slaves_to_kernel(saved_vmlinux_addr);
-
-	return finalize_chain();
-}
-
 void kexec_platform_init(struct boot_param_header *dt_blob)
 {
 	slaves_are_low();
@@ -226,8 +205,7 @@ void kexec_platform_init(struct boot_par
 	init_flat_tree(dt_blob);
 
 	platform_ops.find_vmlinuz = find_vmlinux_in_initramfs;
-	platform_ops.vmlinux_alloc = kexec_vmlinux_alloc;
+	platform_ops.vmlinux_alloc = ranges_vmlinux_alloc;
 	platform_ops.fixups = kexec_fixups;
-	finalize_chain = dt_ops.finalize;
-	dt_ops.finalize = kexec_finalize;
+	platform_ops.start_smp = send_slaves_to_kernel;
 }
Index: work.git/arch/powerpc/boot/main.c
===================================================================
--- work.git.orig/arch/powerpc/boot/main.c	2007-07-10 04:39:43.000000000 -0500
+++ work.git/arch/powerpc/boot/main.c	2007-07-10 04:39:43.000000000 -0500
@@ -212,6 +212,9 @@ void start(void)
 	else
 		printf(" using OF tree (promptr=%p)\n\r", loader_info.promptr);
 
+	if (platform_ops.start_smp)
+		platform_ops.start_smp(vmlinux.addr);
+
 	if (console_ops.close)
 		console_ops.close();
 
Index: work.git/arch/powerpc/boot/ops.h
===================================================================
--- work.git.orig/arch/powerpc/boot/ops.h	2007-07-10 04:39:43.000000000 -0500
+++ work.git/arch/powerpc/boot/ops.h	2007-07-10 04:39:43.000000000 -0500
@@ -35,6 +35,7 @@ struct platform_ops {
 	void *	(*realloc)(void *ptr, unsigned long size);
 	void	(*exit)(void);
 	void *	(*vmlinux_alloc)(unsigned long size);
+	void	(*start_smp)(void *vmlinux);
  	void	(*find_vmlinuz)(struct gunzip_state *, void **srcp,
  			unsigned long *lenp);
 };

^ permalink raw reply

* [PATCH 13/15] bootwrapper: attach an empty vmlinux
From: Milton Miller @ 2007-07-10 22:12 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
In-Reply-To: <boot-6-00.miltonm@bga.com>

Allow the boot wrapper code to be linked without an attached vmlinux.

Rather than invent a new syntax to invoke the wrapper, attach the
stripped version of empty.o, which produces the same result.

This new intermediary is called zBoot.

Signed-off-by: Milton Miller <miltonm@bga.com>
--- 
Initial attempts to remove the dependency on vmlinux in the arch Makefile
have lead to multiple make commands competing in the boot directory and
destroying each other.

Index: work.git/arch/powerpc/boot/Makefile
===================================================================
--- work.git.orig/arch/powerpc/boot/Makefile	2007-07-10 16:38:01.000000000 -0500
+++ work.git/arch/powerpc/boot/Makefile	2007-07-10 16:41:01.000000000 -0500
@@ -124,7 +124,8 @@ endif
 # args (to if_changed): 1 = (this rule), 2 = platform, 3 = dts 4=dtb 5=initrd
 quiet_cmd_wrap	= WRAP    $@
       cmd_wrap	=$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
-		$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
+		$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) \
+		$(if $6,$6,vmlinux)
 
 kexec-$(CONFIG_PPC32)			+= zImage.kexec
 kexec-$(CONFIG_PPC64)			+= zImage.kexec64
@@ -142,6 +143,7 @@ image-$(CONFIG_PPC_PRPMC2800)		+= zImage
 image-$(CONFIG_PPC_ISERIES)		+= zImage.iseries
 image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
 image-$(CONFIG_KEXEC)			+= $(kexec-y)
+image-$(CONFIG_KEXEC)			+= $(patsubst zImage%,zBoot%,$(kexec-y))
 
 ifneq ($(CONFIG_DEVICE_TREE),"")
 image-$(CONFIG_PPC_83xx)		+= cuImage.83xx
@@ -190,6 +192,9 @@ $(obj)/vmlinux.strip: vmlinux
 $(obj)/zImage.iseries: vmlinux
 	$(STRIP) -s -R .comment $< -o $@
 
+$(obj)/zBoot.%: $(wrapperbits)
+	$(call if_changed,wrap,$*,,,,$(obj)/empty.o)
+
 $(obj)/zImage.ps3: vmlinux  $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts
 	$(STRIP) -s -R .comment $< -o vmlinux.strip
 	$(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,)
@@ -227,7 +232,7 @@ clean-files += $(image-) $(initrd-) zIma
 	treeImage.* $(kexec-)
 
 # clean up files cached by wrapper
-clean-kernel := vmlinux.strip vmlinux.bin
+clean-kernel := vmlinux.strip vmlinux.bin empty.o.bin
 clean-kernel += $(addsuffix .gz,$(clean-kernel))
 # If not absolute clean-files are relative to $(obj).
 clean-files += $(addprefix $(objtree)/, $(clean-kernel))
Index: work.git/arch/powerpc/boot/wrapper
===================================================================
--- work.git.orig/arch/powerpc/boot/wrapper	2007-07-10 16:37:30.000000000 -0500
+++ work.git/arch/powerpc/boot/wrapper	2007-07-10 16:41:01.000000000 -0500
@@ -161,6 +161,13 @@ ps3)
     ;;
 esac
 
+if [ "$kernel" = $object/empty.o ] ; then
+    ext=bin
+    objflags="-O binary"
+    gzip=
+fi
+
+
 vmz="$tmpdir/`basename \"$kernel\"`.$ext"
 if [ -z "$cacheit" -o ! -f "$vmz$gzip" -o "$vmz$gzip" -ot "$kernel" ]; then
     ${CROSS}objcopy $objflags "$kernel" "$vmz.$$"

^ permalink raw reply

* [PATCH 12/15] bootwrapper: extract the vmlinux from initramfs
From: Milton Miller @ 2007-07-10 22:12 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
In-Reply-To: <boot-6-00.miltonm@bga.com>

Teach the kexec platform to find the vmlinux from the initramfs.

The implementation searches the initramfs for a file specified
by the boot-file property in chosen.


Signed-off-by: Milton Miller <miltonm@bga.com>
--- 
Status: working.

Index: work.git/arch/powerpc/boot/kexec.c
===================================================================
--- work.git.orig/arch/powerpc/boot/kexec.c	2007-07-10 04:01:57.000000000 -0500
+++ work.git/arch/powerpc/boot/kexec.c	2007-07-10 04:04:09.000000000 -0500
@@ -23,6 +23,8 @@
 #include "flatdevtree.h"
 #include "page.h"
 #include "types.h"
+#include "cpio.h"
+#include "stat.h"
 
 extern char _start[];
 extern char _end[];
@@ -92,6 +94,51 @@ static void find_rmo_end(void)
 	rmo_end = (void *)*rp;
 }
 
+void find_vmlinux_in_initramfs(struct gunzip_state *state,
+		void **srcp, unsigned long *lenp)
+{
+	void *devp;
+	int rc;
+	char path[MAX_PATH];
+
+	if (!loader_info.initrd_size)
+		dt_find_initrd();
+	if (!loader_info.initrd_size)
+		fatal("find_vmlinux: no initramfs");
+	devp = finddevice("/chosen");
+	if (!devp)
+		fatal("find_vmlinux: no /chosen to find vmlinux");
+	rc = getprop(devp, "boot-file", path, sizeof(path));
+	if (rc < 0)
+		fatal("find_vmlinux: no boot-file property in /chosen")
+	else if (rc == 0 || rc > MAX_PATH)
+		fatal("boot-file too long in /chosen")
+
+	rc = find_in_initramfs(path, (void *)loader_info.initrd_addr,
+			loader_info.initrd_size, state);
+	if (!rc)
+		fatal("find_vmlinux: couldn't find boot-file %s in initramfs",
+				path);
+
+	rc = get_cpio_file_mode();
+	if (!S_ISREG(rc))
+		fatal("find_vmlinux: boot-file %s is not a regular file",
+				path)
+
+	get_cpio_info(srcp, &rc);
+	*lenp = get_cpio_file_size();
+}
+
+void cpio_error(char *msg)
+{
+	void *srcp;
+	int read;
+
+	get_cpio_info(&srcp, &read);
+
+	fatal("cpio_error at %p + 0x%x(%d): %s", srcp, read, read, msg);
+}
+
 /**
  * setup_initial_heap - setup a small heap in the bss
  * Using a preallocated heap, setup for scanning the device tree.
@@ -178,6 +225,7 @@ void kexec_platform_init(struct boot_par
 	ranges_init_malloc();
 	init_flat_tree(dt_blob);
 
+	platform_ops.find_vmlinuz = find_vmlinux_in_initramfs;
 	platform_ops.vmlinux_alloc = kexec_vmlinux_alloc;
 	platform_ops.fixups = kexec_fixups;
 	finalize_chain = dt_ops.finalize;

^ permalink raw reply

* [PATCH 11/15] bootwrapper: allow vmlinuz to be an external payload
From: Milton Miller @ 2007-07-10 22:12 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
In-Reply-To: <boot-6-00.miltonm@bga.com>

Allow the boot wrapper to obtain the vmlinux elf from an external
platform supplied location instead of embedding it at link time.

When used with the cpio library, the kernel can be stored as a file
an file in the initramfs, allowing the same (compressed) copy of
the vmlinux elf to be used for both the kernel to execute and any
user space tools such as kexec (for reboot), crash dump, or oprofile.

Another use would be to uncompress directly from a memory mapped
region such as a flash partition.

Signed-off-by: Milton Miller <miltonm@bga.com>
--- 
Check for no find_vmlinuz method before calling it.

The source and source len varables are passed to the routine only
to allow them to be printed later.

This patch follows the current policy of using linker attached data
in preference to platform supplied data (matching the initrd and
command line).

While the platform could supply archive-start, length, and offset,
in loader data, it would require decompressing the skiped portion
twice when the offset is not known in advance.

The prpmc2800 code shows that this hook to find the kernel and the
the code to uncompress the header may want to be separated from the
vmlinux alloc, decompress, and flush code.  I haven't explored an
actual split.

Index: work.git/arch/powerpc/boot/main.c
===================================================================
--- work.git.orig/arch/powerpc/boot/main.c	2007-07-10 03:44:40.000000000 -0500
+++ work.git/arch/powerpc/boot/main.c	2007-07-10 04:04:02.000000000 -0500
@@ -47,10 +47,19 @@ static struct addr_range prep_kernel(voi
 	struct elf_info ei;
 	int len;
 
-	/* gunzip the ELF header of the kernel */
-	gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
-	gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
+	/* Initialze zlib.  Any attached kernel overrides find_vmlinuz */
+	if (vmlinuz_size)
+		gunzip_start(&gzstate, vmlinuz_addr, vmlinuz_size);
+	else
+		if (platform_ops.find_vmlinuz)
+			platform_ops.find_vmlinuz(&gzstate, &vmlinuz_addr,
+					&vmlinuz_size);
+		else
+			fatal("Can't find a kernel to boot: no attached "
+				"vmlinuz and no find_vmlinuz method\n\r");
 
+	/* gunzip and parse the ELF header of the kernel */
+	gunzip_exactly(&gzstate, elfheader, sizeof(elfheader));
 	if (!parse_elf64(elfheader, &ei) && !parse_elf32(elfheader, &ei))
 		fatal("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
 
Index: work.git/arch/powerpc/boot/ops.h
===================================================================
--- work.git.orig/arch/powerpc/boot/ops.h	2007-07-10 04:01:57.000000000 -0500
+++ work.git/arch/powerpc/boot/ops.h	2007-07-10 04:04:02.000000000 -0500
@@ -24,6 +24,8 @@ typedef void (*kernel_entry_t)(unsigned 
 
 struct boot_param_header;
 
+struct gunzip_state;
+
 /* Platform specific operations */
 struct platform_ops {
 	void	(*fixups)(void);
@@ -33,6 +35,8 @@ struct platform_ops {
 	void *	(*realloc)(void *ptr, unsigned long size);
 	void	(*exit)(void);
 	void *	(*vmlinux_alloc)(unsigned long size);
+ 	void	(*find_vmlinuz)(struct gunzip_state *, void **srcp,
+ 			unsigned long *lenp);
 };
 extern struct platform_ops platform_ops;
 

^ permalink raw reply

* [PATCH 10/15] bootwrapper: add cpio file extraction library.
From: Milton Miller @ 2007-07-10 22:11 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, David Gibson
In-Reply-To: <boot-6-00.miltonm@bga.com>

Add a library to search through a cpio or initramfs to a specified
path contained in a cpio.

Signed-off-by: Milton Miller <miltonm@bga.com>
--- 
Status: tested and working.  

This file is designed to also be usable in a stand alone user space
application.

Index: work.git/arch/powerpc/boot/cpio.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ work.git/arch/powerpc/boot/cpio.c	2007-07-10 04:03:40.000000000 -0500
@@ -0,0 +1,306 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright 2007 IBM Corporation.
+ *
+ * Authors: Milton Miller <miltonm@bga.com>
+ *
+ */
+
+#include "cpio.h"
+#include "string.h"
+
+struct cpio_header {
+	char ino[8];
+	char mode[8];
+	char uid[8];
+	char gid[8];
+	char nlink[8];
+	char mtime[8];
+	char filesize[8];
+	char maj[8];
+	char min[8];
+	char rmaj[8];
+	char rmin[8];
+	char namesize[8];
+	char chksum[8];
+} cpio_header_buf;
+
+static int check_magic(char magic[6])
+{
+	return !memcmp(magic,"070701",6) || !memcmp(magic,"070702",6);
+}
+
+static int read_magic(struct gunzip_state *stream)
+{
+	int len;
+	char magic[6];
+
+	len = gunzip_partial(stream, magic, sizeof(magic));
+	if (len == 0)
+		return 0;
+
+	if (len == sizeof(magic) && check_magic(magic))
+		return len;
+
+
+	/* Not the right magic or short read.  We might have stumbled
+	 * onto a compressed archive immediately following an
+	 * uncompressed one, or just some NUL bytes at the end of the
+	 * archive.  Inform the higher layers by the negative length.
+	 */
+	return -len;
+}
+
+static int get_cpio_header(struct gunzip_state *stream)
+{
+	int len;
+
+	len = read_magic(stream);
+	if (len <= 0)
+		return len;
+
+	gunzip_exactly(stream, &cpio_header_buf, sizeof(cpio_header_buf));
+	len += sizeof(cpio_header_buf);
+
+	return len;
+}
+
+static unsigned int cpio_str_to_num(char hexascii[8])
+{
+	unsigned int num = 0;
+	char c;
+	int d;
+
+	for (d=0; d < 8; d++) {
+		c = hexascii[d];
+		num <<= 4;
+		if (c >= '0' && c <= '9') {
+			num += c - '0';
+		} else if (c >= 'A' && c <= 'F') {
+			num += c - 'A' + 10;
+		} else if (c >= 'a' && c <= 'f') {
+			num += c - 'a' + 10;
+		} else {
+			cpio_error("bad cpio archive header: "
+					"invalid a hex digit");
+		}
+	}
+
+	return num;
+}
+
+static char name_buf[MAX_PATH+1];
+static const char cpio_end[] = "TRAILER!!!";
+#define CPIO_END_LEN sizeof(cpio_end)
+
+/* check_next_file
+ * Look for @path in @stream.  Set @consumed to the number of bytes
+ * succesfully read and processed.  return 1 on match, 0 for discarding
+ * an unmatched file, -1 on end of archive (either detected trailer or
+ * EOF on stream), or -(1 + bytes read) for a short read or bad magic
+ * number.  (For the short or bad read, the consumed is not changed).
+ */
+static int check_next_file(char *path, int pathlen,
+		struct gunzip_state *stream, int *consumed)
+{
+	int len, total, match;
+
+	if (pathlen > MAX_PATH) {
+		cpio_error("path too long to search\n");
+	}
+	total = get_cpio_header(stream);
+	if (total <= 0)
+		return total - 1;
+
+	len = cpio_str_to_num(cpio_header_buf.namesize);
+
+	if (len == pathlen || len == CPIO_END_LEN) {
+		gunzip_exactly(stream, name_buf, len);
+		total += len;
+		match = !strcmp(name_buf, path);
+		if (!match && !cpio_str_to_num(cpio_header_buf.filesize))
+			match = -!strcmp(name_buf, cpio_end);
+	} else {
+		gunzip_discard(stream, len);
+		total += len;
+		name_buf[0] = '\0';
+		match = 0;
+	}
+
+	len = total % 4;
+	if (len) {
+		gunzip_discard(stream, 4 - len);
+		total += 4 - len;
+	}
+
+	if (!match) {
+		len = cpio_str_to_num(cpio_header_buf.filesize);
+		gunzip_discard(stream, len);
+		total += len;
+
+		len = total % 4;
+		if (len) {
+			gunzip_discard(stream, 4 - len);
+			total += 4 - len;
+		}
+	}
+
+	*consumed += total;
+	return match;
+}
+
+static char *this_buf;
+static int this_archive;
+
+/* find_in_cpio.
+ * find a pathname @path in a single cpio archive described by @stream.
+ * Return is the same as check_next_file.
+ */
+int find_in_cpio(char *path, struct gunzip_state *stream)
+{
+	int found;
+	int pathlen = strlen(path) + 1;
+
+	this_archive = 0;
+	do {
+		found = check_next_file(path, pathlen, stream, &this_archive);
+	} while (found == 0);
+
+	return found;
+}
+
+/* find_in_initramfs
+ * Search a initramfs buffer for a given path name.  Returns 0 on
+ * not found, or 1 with @state ready to read the file.
+ *
+ * Note: this returns the first match, not the last.   The kernel
+ * decompressor  effectivly uses the last match.  This code also
+ * doesn't worry about the directories in the path existing.
+ */
+int find_in_initramfs(char *path, char *buf, int len,
+		struct gunzip_state *stream)
+{
+	int found, total = 0;
+	int pathlen = strlen(path) + 1;
+	int *ibuf;
+
+	do {
+		/* get to word boundary, but stop if not NUL */
+		for (; total % 4 && total < len - 4; total++)
+			if (buf[total])
+				break;
+
+		if ((total % 4) == 0) {
+			/* fast forward over NUL words.  */
+			for (ibuf = (int *)&buf[total];
+					total < len - sizeof(*ibuf) && !*ibuf;
+					ibuf++)
+			total += sizeof(*ibuf);
+		}
+
+		/* check remainder of a short archive -- it must all be
+		 * zero as both gzip header and cpio header are bigger
+		 * than this.
+		 */
+		if (total >= len - 4) {
+			for (;total < len; total++) {
+				if (buf[len]) {
+					cpio_error("Junk at end of buffer");
+				}
+			}
+			break;
+		}  else if (total % 4) {
+			/*
+			 * If we are unalinged and not at the end of the buffer
+			 * we must be following a compressed archive.  Only
+			 * NUL and gzip headers are allowed.  We skipped NUL.
+			 */
+			if (!(buf[total] == 0x1b && buf[total + 1] == 0x8b))
+				cpio_error("unalinged junk in buffer");
+		}
+
+		this_buf = buf + total;
+		this_archive = 0;
+
+		gunzip_start(stream, this_buf, len - total);
+
+		do {
+			found = check_next_file(path, pathlen, stream,
+					&this_archive);
+		} while (!found);
+
+		if (found > 0)
+			return found;
+
+		if (stream->s.workspace) {
+			int discard;
+
+			if (found < -1) {
+				cpio_error("Junk in compressed archive");
+			}
+
+			/* we either found EOF or TRAILER!!!.  In the later
+			 * case we need to discard to the end of the gzip
+			 * contents.
+			 */
+			do {
+				discard =  gunzip_partial(stream, name_buf,
+					MAX_PATH);
+				this_archive += discard;
+			} while (discard);
+
+			/*
+			 * Peek at how many input bytes were consumed.
+			 * reset our consumed input.
+			 */
+			total += stream->s.total_in + 8;
+
+			/* clean up zlib */
+			discard = gunzip_finish(stream, name_buf, 0);
+		} else {
+			if (this_archive % 4) {
+				cpio_error("Archive not multiple of 4?");
+			}
+			total += this_archive;
+
+			if (!this_archive) {
+				cpio_error("junk between archives");
+			}
+			/* don't check the < -1 of found, it might be an
+			 * archive.  This will be caught by the !this_archive
+			 * check on the next loop.
+			 */
+		}
+	} while (total < len);
+
+	return 0;
+}
+
+void get_cpio_info(void **archive_start, int *consumed)
+{
+	*archive_start = this_buf;
+	*consumed = this_archive;
+}
+
+int get_cpio_file_mode(void)
+{
+	return cpio_str_to_num(cpio_header_buf.mode);
+}
+
+int get_cpio_file_size(void)
+{
+	return cpio_str_to_num(cpio_header_buf.filesize);
+}
Index: work.git/arch/powerpc/boot/cpio.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ work.git/arch/powerpc/boot/cpio.h	2007-07-10 04:03:40.000000000 -0500
@@ -0,0 +1,12 @@
+#include "gunzip_util.h"
+
+extern int find_in_cpio(char *path, struct gunzip_state *stream);
+extern int find_in_initramfs(char *path, char *buf, int len,
+		struct gunzip_state *state);
+extern void get_cpio_info(void **archive_start, int *consumed);
+extern int get_cpio_file_size(void);
+extern int get_cpio_file_mode(void);
+
+#define MAX_PATH 256
+
+extern void cpio_error(char *msg);
Index: work.git/arch/powerpc/boot/Makefile
===================================================================
--- work.git.orig/arch/powerpc/boot/Makefile	2007-07-10 04:02:24.000000000 -0500
+++ work.git/arch/powerpc/boot/Makefile	2007-07-10 04:03:57.000000000 -0500
@@ -36,13 +36,13 @@ $(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
 
 zlib       := inffast.c inflate.c inftrees.c
 zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
-zliblinuxheader := zlib.h zconf.h zutil.h
+zliblinuxheader := zlib.h zconf.h zutil.h stat.h
 
 $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \
 	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
 
 src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
-		flatdevtree_conv.c marshal.c memranges.c kexec.c \
+		flatdevtree_conv.c marshal.c memranges.c kexec.c cpio.c \
 		ns16550.c serial.c simple_alloc.c div64.S util.S rtas.c \
 		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
 		44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox