Re: [PATCH v2 03/10] pylibfdt: Add support for the rest of the header functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



On Sat, Jun 09, 2018 at 11:12:44AM -0800, Simon Glass wrote:
> Hi David,
> 
> On 8 June 2018 at 04:27, David Gibson <david@xxxxxxxxxxxxxxxxxxxxx> wrote:
> > On Wed, Jun 06, 2018 at 03:37:02PM -0600, Simon Glass wrote:
> >> Export all of these through Python.
> >>
> >> Signed-off-by: Simon Glass <sjg@xxxxxxxxxxxx>
> >> ---
> >>
> >> Changes in v2:
> >> - Drop use of check_err() since these functions cannot fail
> >> - Update existing header functions to also drop check_err()
> >>
> >>  pylibfdt/libfdt.i       | 71 +++++++++++++++++++++++++++++++++++++++--
> >>  tests/pylibfdt_tests.py |  8 +++++
> >>  2 files changed, 76 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i
> >> index 94c3d00..f33e2ab 100644
> >> --- a/pylibfdt/libfdt.i
> >> +++ b/pylibfdt/libfdt.i
> >> @@ -252,21 +252,86 @@ class Fdt:
> >>          """
> >>          return check_err(fdt_next_subnode(self._fdt, nodeoffset), quiet)
> >>
> >> +    def magic(self):
> >> +        """Return the magic word from the header
> >> +
> >> +        Returns:
> >> +            Magic word
> >> +        """
> >> +        # Use a mask to ensure that this does not return a -ve number
> >> +        return fdt_magic(self._fdt) & 0xffffffff
> >
> > You still have the mask here for no clear reason.
> 
> Python's numbers are a little strange. If the top bit of a 32-bit
> number is set, this means it is a negative number in two-complement
> arithmetic, as you know. Python will then use a negative value instead
> of positive. To force it to regard the number as unsigned, we must
> mask it. This is how I have learned to do it in Python, but maybe
> there is a better way?

Two observations first:

1) I'm pretty sure this will only apply on 32-bit platforms
(specifically those where a C "long" and therefore a Python int() are
32-bit).

2) I think this has more to do with the swig typemapping that the
integers in Python per se.  On a 32-bit platform I can do this in
Python:
    >>> (1 << 31)
    2147483648L

So we're getting the expected answer... but as a Python long rather
than a Python int (it's a Python int when run on a 64-bit platform).

So what seems to be happening here is that on the C side (not sure if
it's in stuff you've written or in swig's generated magic), we're
forcing the 'uint32_t' into a 'long', then stuffing that into a Python
integer.

The mask strips away the sign, and at the same time coerces the value
into a Python long (because 0xffffffff will be a PyLong on such a
platform).

> To see the impact, try removing the mask. You will see that magic()
> will return a -ve number, rather than unsigned.

So, the thing that bothers me a bit here is that it's not the same for
all the header functions, even though they all return uint32_t on the
C side.  I guess we get away with in practice, because apart from
'magic' all the other values should actually fit in 31 bits.  Could
still cause confusing answers on a malformed fdt, of course.

I think the right solution is to alter the swig stuff so that on
platforms where sizeof(long) <= 4 we make the header functions return
a PyLong instead of a PyInt. I'm not immediately sure how to do that,
however.

I guess the current approach will work for now, even if it is a hack,
so I'll go ahead and apply it, and we can try to fix it up later.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux